I have devs using windows and linux builds of CodeBlocks, and each version keeps flipping the directory separator ('/' vs '\'), making it a pain to see what the is actually changed in the project when viewing diffs. Is there a way to make CodeBlocks stop changing it, or make both versions always use the same (I prefer linux '/'). I could look at doing it myself, but wanted to make sure I had not overlooked a configuration option, and would not want to invest time in adding/modifying code if others thought this was not useful or it would cause other problems that I'm not thinking about.
Code BLocks is not changing this but the operating systems are.
Maybe it would be a good idea to standardize on directory separator and newline symbols in code blocks files.
Since Code::Blocks itself is cross platform it seems very practical to make file descriptions also cross platform.
Using '/' (also my preference) for directory separator and /r/n for a new line. (There is a technical reason to use this and not /n, but I forgot what that was.)
Try this patch:
Index: src/sdk/globals.cpp
===================================================================
--- src/sdk/globals.cpp (revision 8133)
+++ src/sdk/globals.cpp (working copy)
@@ -201,6 +201,11 @@
return result;
}
+wxString NativeToUnix(const wxString& filename)
+{
+ wxFileName fname(filename);
+ return fname.GetFullPath(wxPATH_UNIX);
+}
void QuoteStringIfNeeded(wxString& str)
{
Index: src/sdk/projectloader.cpp
===================================================================
--- src/sdk/projectloader.cpp (revision 8133)
+++ src/sdk/projectloader.cpp (working copy)
@@ -1175,7 +1175,7 @@
{
wxFileName fname(outputFileName);
fname.ClearExt();
- outputFileName = fname.GetFullPath();
+ outputFileName = fname.GetFullPath(wxPATH_UNIX);
}
if ( (prefixPolicy == tgfpPlatformDefault)
@@ -1197,7 +1197,7 @@
if (!outputFileNameWOPrefix.IsEmpty())
{
fname.SetFullName(outputFileNameWOPrefix);
- outputFileName = fname.GetFullPath();
+ outputFileName = fname.GetFullPath(wxPATH_UNIX);
}
}
}
@@ -1207,19 +1207,19 @@
if (target->GetTargetType() == ttDynamicLib)
{
if (target->GetDynamicLibImportFilename() != _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)"))
- outnode->SetAttribute("imp_lib", cbU2C(target->GetDynamicLibImportFilename()));
+ outnode->SetAttribute("imp_lib", cbU2C(NativeToUnix(target->GetDynamicLibImportFilename())));
if (target->GetDynamicLibImportFilename() != _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)"))
- outnode->SetAttribute("def_file", cbU2C(target->GetDynamicLibDefFilename()));
+ outnode->SetAttribute("def_file", cbU2C(NativeToUnix(target->GetDynamicLibDefFilename())));
}
outnode->SetAttribute("prefix_auto", prefixPolicy == tgfpPlatformDefault ? "1" : "0");
outnode->SetAttribute("extension_auto", extensionPolicy == tgfpPlatformDefault ? "1" : "0");
if (target->GetWorkingDir() != _T("."))
- AddElement(tgtnode, "Option", "working_dir", target->GetWorkingDir());
+ AddElement(tgtnode, "Option", "working_dir", NativeToUnix(target->GetWorkingDir()));
if (target->GetObjectOutput() != _T(".objs"))
- AddElement(tgtnode, "Option", "object_output", target->GetObjectOutput());
+ AddElement(tgtnode, "Option", "object_output", NativeToUnix(target->GetObjectOutput()));
if (target->GetDepsOutput() != _T(".deps"))
- AddElement(tgtnode, "Option", "deps_output", target->GetDepsOutput());
+ AddElement(tgtnode, "Option", "deps_output", NativeToUnix(target->GetDepsOutput()));
}
if (!target->GetExternalDeps().IsEmpty())
AddElement(tgtnode, "Option", "external_deps", target->GetExternalDeps());
@@ -1377,7 +1377,7 @@
ProjectFile* f = pfa[i];
FileType ft = FileTypeOf(f->relativeFilename);
- TiXmlElement* unitnode = AddElement(prjnode, "Unit", "filename", f->relativeFilename);
+ TiXmlElement* unitnode = AddElement(prjnode, "Unit", "filename", NativeToUnix(f->relativeFilename));
if (!f->compilerVar.IsEmpty())
{
wxString ext = f->relativeFilename.AfterLast(_T('.')).Lower();
@@ -1404,7 +1404,7 @@
AddElement(unitnode, "Option", "weight", f->weight);
if (!f->virtual_path.IsEmpty())
- AddElement(unitnode, "Option", "virtualFolder", f->virtual_path);
+ AddElement(unitnode, "Option", "virtualFolder", NativeToUnix(f->virtual_path));
// loop and save custom build commands
for (pfCustomBuildMap::iterator it = f->customBuild.begin(); it != f->customBuild.end(); ++it)
Index: src/include/globals.h
===================================================================
--- src/include/globals.h (revision 8133)
+++ src/include/globals.h (working copy)
@@ -181,6 +181,7 @@
extern DLLIMPORT void AppendArray(const wxArrayString& from, wxArrayString& to);
extern DLLIMPORT wxString UnixFilename(const wxString& filename);
+extern DLLIMPORT wxString NativeToUnix(const wxString& filename);
extern DLLIMPORT void QuoteStringIfNeeded(wxString& str);
/// Escapes spaces and tabs (NOT quoting the string)
Quote from: Alpha on July 16, 2012, 04:05:41 AM
Try this patch:
This is a nice work, however, it is not that easy, and therefoe this patch is incomplete:
- include directories are not converted
- commands are not converted (that's a tricky part, as e.g. zip -jq9 devel/share/CodeBlocks/resources.zip *.png won't work on some zip distros on Windows)
- command line parameters are not converted, tricky, too
- external deps are not converted
- UNC names / path's are not handled correctly
- Why didn't you use the existing UnixFilename method? NativeToUnix won'T work with macros IMHO, and macros should be considered for path's.
So in the end the user is responsible for doing some of these points, maybe, but nevertheless you still get two different project files if you save the same under Linux and Windows. :-\ :(
...just an idea: Wouldn't it be enough to use generally use UnixFilename (including the places where you converted wxFileName to wxPATH_UNIX and used NativeToUnix), but then implement the Windows part in this method as following:
if (platform::windows)
{
bool unc_name = result.StartsWith(_T("\\\\"));
while (result.Replace(_T("/"), _T("\\")))
;
while (result.Replace(_T("\\\\"), _T("\\")))
;
if (unc_name)
result = _T("\\") + result;
else // THIS PART IS NEW!!!
{
while (result.Replace(_T("\\"), _T("/")))
;
}
}
...here comes an alternative patch accordingly.
Edit: Patch updated (see more recent post).
Seems like most practical thing to do is to use:
- Relative paths as much as possible
- Automatically convert the directory separator.
We should have codeblocks checking on which platform it is in and use/change the separators accordingly.
With standardizing path description internally we could avoid things switching constantly I guess?
(Modifying them to correct representation when giving to other applications/command line?)
Quote from: Hadomunt on July 27, 2012, 06:42:42 PM
Seems like most practical thing to do is to use:
- Relative paths as much as possible
- Automatically convert the directory separator.
That's how it is now and what was complained. ::)
If that's OK we don't need to change anything. ???
Quote from: MortenMacFly on July 28, 2012, 03:13:32 PM
Quote from: Hadomunt on July 27, 2012, 06:42:42 PM
Seems like most practical thing to do is to use:
- Relative paths as much as possible
- Automatically convert the directory separator.
That's how it is now and what was complained. ::)
If that's OK we don't need to change anything. ???
If I understand the post correctly the conversion should only be done if we call any external programs, like compiler, linker etc. , but internally (especially in project- and workspace-files) use the same syntax on all platforms.
This might probaly lead to problems with (windows-) parameters that get saved in the project-file, because they also use a slash in many (most?) cases.
Quote from: jens on July 28, 2012, 03:26:53 PM
If I understand the post correctly the conversion should only be done if we call any external programs, like compiler, linker etc. , but internally (especially in project- and workspace-files) use the same syntax on all platforms.
Ah, OK... ::)
Quote from: jens on July 28, 2012, 03:26:53 PM
This might probaly lead to problems with (windows-) parameters that get saved in the project-file, because they also use a slash in many (most?) cases.
That what my approach tries to avoid: I only change path's we can change safely w/o interfering with tools not supporting it (although I have to admit that I never tried to compile a file using MSVC with this patch applied). For Windows, you
cannot easily convert all back-slashes to slashes. For this I see no way - just consider this command line:
mytool.exe /lflag C:\Foo\Bar \\server\baz /DDEFHow would you safely do the right thing here? Impossible.
The main request was out of the fact that if you saved a cross-platform project with Windows and then with Unix the files are different. With the patch presented here they wouldn't. I honestly think that's all we can do. Everything else is just too risky and would certainly work on the one hand, but break a feature on the other.
Quote from: MortenMacFly on July 19, 2012, 08:54:17 AM
...here comes an alternative patch accordingly.
For the record: Both patches have serious side-effects. The most serious one is that having these applied and using macros related to one of these path's on Windows will break the console commands, as e.g.
"
copy myfoldel/fo/bar .." won't work on Windows. So either there is a
context and
platform sensitive way to convert the path correctly or it remains as it is.
As I don't see a way w/o
much and error-prone effort for the first choice I'm afraid the second is the way to go. ::)
In my opinion, anything saved to a
.cbp (or
.workspace) that has an internal representation as a path or a file name should be saved with
"/" and converted (in memory) to the native format on load. (Attempting conversion of anything else - command line parameters, pre/post-build steps - would both be unwise and unlikely to work reliably.)
This would remain completely backwards compatible, and deal with enough cases to (mostly) take care of the original problem: sharing the same project file between Windows and Linux.
Quote from: MortenMacFly on July 19, 2012, 08:28:01 AM
- Why didn't you use the existing UnixFilename method?
(Very late reply :), but) I was reading/writing quickly and missed it.
Quote from: Alpha on August 07, 2012, 03:39:33 PM
In my opinion, anything saved to a .cbp (or .workspace) that has an internal representation as a path or a file name should be saved with "/" and converted (in memory) to the native format on load.
Well and
that is the problem: You don't know, if pre- or post-build steps (for example) are a path or if a "\" or "/" is part of a macro etc.. So it
is error-prone. There is no such easy thing like "convert on load" without making mistakes. Only the user knows how (s)he would like to interpret / setup such things. So its best to leave it as setup by the user IMHO.
BTW: And a partial solution makes no sense, too - because then you still have differences.
Quote from: MortenMacFly on August 07, 2012, 05:04:24 PM
BTW: And a partial solution makes no sense, too - because then you still have differences.
Yes, but they will be far less. And adding a file to the project won't cause conflicts.
For the macros aren't we saving them as the user have typed them? For example "$(MY_MACRO)/test" is save as is.
My opinion is that we must not modify anything the users has typed with the keyboard and we should modified anything entered by a paths-like dialog.
So the "other options" in the linker/compiler or the "post/pre build steps" won't be changed, they will be save as entered.
The paths in the search paths section of the settings will be save in unix/dos format (doesn't matter which, but I prefer unix of course:) ).
And if we want to preserve the cross platform support we can provide a marco to convert a path to native format, which can be used in the non-converted sections.
It will be a little tedious to setup, but it will be explicit and not work auto magically.
p.s. this is the second time I post similar answer, the first time the post gone missing for some strange reason...
Quote from: MortenMacFly on August 07, 2012, 05:04:24 PM
Well and that is the problem: You don't know, if pre- or post-build steps (for example) are a path or if a "\" or "/" is part of a macro etc.. So it is error-prone.
Quote from: Alpha on August 07, 2012, 03:39:33 PM
(Attempting conversion of anything else - command line parameters, pre/post-build steps - would both be unwise and unlikely to work reliably.)
?! I was only suggesting using this on variables that Code::Blocks already
knows are guaranteed to only be paths or file names. From Project file format (http://wiki.codeblocks.org/index.php?title=Project_file), the variables that are saved in:
<Script file="" />
<Option output="default" prefix_auto="1" extension_auto="1" />
<Option working_dir="." />
<Option object_output=".objs" />
<Option deps_output=".deps" />
<Option external_deps="" />
<Option additional_output="" />
<Option host_application="" />
<Add directory="" />
<Unit filename="BuildScripts/config.script"></Unit>
<Option virtualFolder="" />
Quote from: MortenMacFly on August 07, 2012, 05:04:24 PM
There is no such easy thing like "convert on load" without making mistakes.
For these specific cases (or most of them), Code::Blocks already uses a "convert on load" (this is how it accepts, for example, files with Linux paths on a Windows computer) - which is what caused the problem listed in the first post, it is not standardized which format they save back to.
(Oops, our posts crossed...)
Quote from: oBFusCATed on August 07, 2012, 05:21:39 PM
For the macros aren't we saving them as the user have typed them? For example "$(MY_MACRO)/test" is save as is.
Huh? I doubt this is. If so, my attempt would be OK. I believe "$(MY_MACRO)/test" would be "$(MY_MACRO)\test" on Windows.
Quote from: oBFusCATed on August 07, 2012, 05:21:39 PM
Quote from: MortenMacFly on August 07, 2012, 05:04:24 PM
BTW: And a partial solution makes no sense, too - because then you still have differences.
Yes, but they will be far less. And adding a file to the project won't cause conflicts.
Why wouldn't it? If you add a file on Windows and save creates a different file when adding a file on Linux and save - that's what I experienced with C::B for decades now and that's what I wanted to fix.
Quote from: Alpha on August 07, 2012, 05:27:29 PM
?! I was only suggesting using this on variables that Code::Blocks already knows are guaranteed to only be paths or file names. From Project file format (http://wiki.codeblocks.org/index.php?title=Project_file), the variables that are saved in: [...]
I'm afraid this is not entirely true. For example, the output file and object_output can have macros.
Well - let me suggest another approach: Use my patch, modify it the way you think it is correct and re-send. I'll try with some of my projects that make heavy macros usage and report back. I could also think of at least one thing: Definitely the unit files cause most conflicts and diffs - so if its just for them as an interim-step I am fine.
Why I am so sceptic is that the errors I got were really frustrating, because for example copy operations based on macros that used the
TARGET_OUTPUT_FILE macro (or alike) were suddenly no longer working causing strange effects with my projects because files were not updated as they should have been. This is exactly the side-effects I meant you don't think off in the first place. And btw: The error message was not highlighted, so it took me a while. :-(
Quote from: MortenMacFly on August 07, 2012, 06:19:37 PM
Huh? I doubt this is. If so, my attempt would be OK. I believe "$(MY_MACRO)/test" would be "$(MY_MACRO)\test" on Windows.
My thought was the we're not expanding the marcos before saving the file, so what are the problems if we always save them in unix format?
C::B already does the conversion if the file have been saved on unix, doesn't it?
Quote from: oBFusCATed on August 07, 2012, 05:21:39 PM
Why wouldn't it? If you add a file on Windows and save creates a different file when adding a file on Linux and save - that's what I experienced with C::B for decades now and that's what I wanted to fix.
I think we misunderstand each other.
What I was telling is that the most conflicts happen in the files added to the project, so a partial solution will minimize the problem.
You have said it won't.
Quote from: MortenMacFly on August 07, 2012, 06:19:37 PM
Well - let me suggest another approach: Use my patch, modify it the way you think it is correct and re-send. I'll try with some of my projects that make heavy macros usage and report back. I could also think of at least one thing: Definitely the unit files cause most conflicts and diffs - so if its just for them as an interim-step I am fine.
I will see what I can come up with.
Quote from: Alpha on August 07, 2012, 07:57:11 PM
I will see what I can come up with.
Forget it for a while and try the attached patch... this is my last attempt... ;D :P
Edit: Patch updated (see more recent post).
Quote from: oBFusCATed on August 07, 2012, 06:51:11 PM
What I was telling is that the most conflicts happen in the files added to the project, so a partial solution will minimize the problem.
Yes, but whats the point in "minimising" here? Either it is the same (which would be nice!) or not. But if you are talking about SVN conflicts - I agree.
Quote from: MortenMacFly on August 07, 2012, 08:17:14 PM
Forget it for a while and try the attached patch... this is my last attempt... ;D :P
...ooops: Tiny error in the patch - corrected version here:
Quote from: MortenMacFly on August 07, 2012, 08:19:25 PM
But if you are talking about SVN conflicts - I agree.
Yes, the whole problem is related to SVN/VCS conflicts, as the files are not meant to be edited by humans anyway and if VCS is not used the path separator won't be a problem.
Quote from: MortenMacFly on August 07, 2012, 08:27:02 PM
...ooops: Tiny error in the patch - corrected version here:
BTW - with this patch I got another side-effect: CC does not work well anymore and mixes files. That's exactly what I am talking about with undesired side-effects.
However, I've fixed this in my local copy already. It was actually a bad interface in CC.
Try this patch.
Seem this is reported as bug, once again. See https://sourceforge.net/p/codeblocks/tickets/36/
This seems to affect only libraries whitch contain paths.
See my comment: https://sourceforge.net/p/codeblocks/tickets/36/#7e28
Can you test this patch ?
commit b0baeda27eb28cc1e4b9652b6f49b47d8d1e9d16
Author: Jens Lody <jens@codeblocks.org>
Date: Mon Aug 25 09:31:09 2014 +0200
* fix for bug #36 Path slashes in project file flip on save between windows and nix
Index: src/sdk/projectloader.cpp
===================================================================
--- src/sdk/projectloader.cpp
+++ src/sdk/projectloader.cpp
@@ -1404,7 +1404,7 @@
node = AddElement(tgtnode, "Linker");
AddArrayOfElements(node, "Add", "option", target->GetLinkerOptions());
- AddArrayOfElements(node, "Add", "library", target->GetLinkLibs());
+ AddArrayOfElements(node, "Add", "library", target->GetLinkLibs(), true);
AddArrayOfElements(node, "Add", "directory", target->GetLibDirs(), true);
if (node->NoChildren())
tgtnode->RemoveChild(node);
@@ -1468,7 +1468,7 @@
node = AddElement(prjnode, "Linker");
AddArrayOfElements(node, "Add", "option", m_pProject->GetLinkerOptions());
- AddArrayOfElements(node, "Add", "library", m_pProject->GetLinkLibs());
+ AddArrayOfElements(node, "Add", "library", m_pProject->GetLinkLibs(), true);
AddArrayOfElements(node, "Add", "directory", m_pProject->GetLibDirs(), true);
if (node->NoChildren())
prjnode->RemoveChild(node);
I tested it on linux and windows 7 with relative and absolute paths (including drive-letter on win) and decided to commit it in svn r9859 .
Thanks...