programmatically alter project settings - visual-studio

I have an old MFC solution with 120 projects in it.
Now Im trying to compile it with VisualC 2017 but every project emits the error:
cannot open file mfc140d.lib
Opening project properties, change the platform toolset to VS2017 141 and the the language version to C++17 fixes it.
But it will take a looooong time to do this for 120 projects and then the same for release build. Which are the settings in the project files that I can change programatically to set these two options? I sure cant find them

Wrote a python script that adds stdcpp17 and v141 to the vcxproj file if non existing. Maybe somebody finds a use for it:
def get_all_files(basedir):
for root, subfolders, files in os.walk(basedir):
for file in os.listdir(root):
yield root, file
def all_lines_from_file(file):
with open(file, 'r') as fd:
for line in fd.readlines():
yield line
def update_VCXPROJ():
standard = '<LanguageStandard>stdcpp17</LanguageStandard>'
toolset = '<PlatformToolset>v141</PlatformToolset>'
add1 = '<CharacterSet>MultiByte</CharacterSet>'
add2 = '<DebugInformationFormat>'
for root, file in get_all_files('c:/projects/6thcycle/sources/'):
if not file.lower().endswith('.vcxproj'):
continue
thisfile = ''
for line in all_lines_from_file('{0}/{1}'.format(root, file)):
if toolset in line or standard in line:
continue
if add1 in line:
line += ' {0}\n'.format(toolset)
elif add2 in line:
line += ' {0}\n'.format(standard)
thisfile += line
with open('{0}/{1}'.format(root, file), 'w') as fd:
fd.write(thisfile)
update_VCXPROJ()

Related

Is it possible to sort the Compile Sources list in the Build Phases section of an Xcode project?

I want to sort the files in the 'Compile Sources' section of my Xcode project according to their names. Is it possible?
Yes, you can reorder the Compile Sources section in Xcode, but not from the GUI - which is a shame considering that this is already version 6 of the IDE and they still haven't gotten around to this basic feature.
As A-Live said, you need to edit the project.pbxproj file within the yourproject.xcodeproj file. Use Finder to select the yourproject.xcodeproj file and then use the context menu to Show Package Contents. After that open the project.pbxproj file with a text editor.
Find the PBXSourcesBuildPhase section and copy everything between files = ( and ); into a new text file. Remove the leading tabs/spaces. Save that file somewhere on your disk. Open up a terminal and do this:
sort -bf -t " " -k 3 PBXSourcesBuildPhase.txt > PBXSourcesBuildPhase.sorted.txt
Open up the new PBXSourcesBuildPhase.sorted.txt file in your text editor, copy the sorted lines into the PBXSourcesBuildPhase section of your project.pbxproj (overwrite the lines that you previously copied) and save.
Now you should be able to see all the files sorted in the Compile Sources section in Xcode.
I've tested this in Xcode 6.0.1 with a small project (~150 source files) and had no problems.
Careful: you should make a backup of your project file (or better: use version control) before you try this. Just in case.
I reckon it is a shame that this is not possible.
as a workaround in most of situations, you can use the search filter on the right upper corner of the file list.
for example, I needed to add a compiler flag in many files which (fortunately) all started with the same prefix. to do so, as stated here, you have to double click on a file.
then, I filtered the files for the prefix, shift-clicked them in order to select them all, then released shift and double-clicked one of them. this way I was able to add the flag to all of the files at once
The accepted solution works fine, but it requires manual steps(open the project file, find the section for the target that you want etc.) so it is a little cumbersome and it can not be automated if you need to keep the section sorted each time you perform a build or commit.
I faced with the same problem and I created a ruby script to sort these sections. The script sorts the 'Compile Sources', 'Copy Bundle Resources’ and all the 'Copy files' sections under Build Phase for a specified or all the targets.
#!/usr/bin/env ruby
require 'xcodeproj'
require 'set'
project_file, target_name = ARGV
# open the project
project = Xcodeproj::Project.open(project_file)
# find the target
targets_to_sort = project.native_targets.select { |x| x.name == target_name || target_name.nil? }
phases_to_sort = [Xcodeproj::Project::Object::PBXSourcesBuildPhase, Xcodeproj::Project::Object::PBXCopyFilesBuildPhase, Xcodeproj::Project::Object::PBXResourcesBuildPhase]
targets_to_sort.each do |target|
puts "sorting files for target #{target.name}"
phases_to_sort.each do |phase_to_sort|
target.build_phases.select { |x| x.class == phase_to_sort }.each do |phase|
phase.files.sort! { |l, r| l.display_name <=> r.display_name }
end
end
end
puts 'saving project'
project.save
To sort all targets:
./sort_sources.rb MyProject.xcodeproj
Or to sort only one target:
./sort_sources.rb MyProject.xcodeproj My_Target
It requires the gem xcodeproj:
gem install xcodeproj
This is thoroughly answered, but I thought I'd share the Emacs command that sorted these in place for me. Navigate to project.pbxproj, mark all files under PBXSourcesBuildPhase, and use the command:
M-3 M-x sort-fields
...aka sorting the marked area by the 3rd column, which happens to be the filenames. C-x C-s and you're on your way.
You can reorder the entries of PBXSourcesBuildPhase section at the project.pbxproj, it worked for me but of course there's no guarantee in general for it to work. Don't forget to backup your backups first.

How does F# Interactive #I command know about project path?

Here is the scenario:
Open Visual Studio. This was done in VS2010 Pro.
Open F# Interactive within Visual Studio
Open project with fsx file
Note: Project and fsx file are in E:\<directories>\fsharp-tapl\arith
Send commands to F# Interactive from fsx file
> System.Environment.CurrentDirectory;;
val it : string = "C:\Users\Eric\AppData\Local\Temp"
I was not expecting a Temp directory but it makes sense.
> #r #"arith.exe"
Examples.fsx(7,1): error FS0082: Could not resolve this reference.
Could not locate the assembly "arith.exe".
Check to make sure the assembly exists on disk.
If this reference is required by your code, you may get compilation errors.
(Code=MSB3245)
Examples.fsx(7,1): error FS0084: Assembly reference 'arith.exe' was not found
or is invalid
The #r command error shows that F# Interactive currently does not know the location of arith.exe.
> #I #"bin\Debug"
--> Added 'E:\<directories>\fsharp-tapl\arith\bin\Debug'
to library include path
So we tell F# Interactive the location of the arith.exe.
Notice that the path is NOT an absolute path but a sub-path of the project.
I have not told F# Interactive the location of the arith project
E:\<directories>\fsharp-tapl\arith
> #r #"arith.exe"
--> Referenced 'E:\<directories>\fsharp-tapl\arith\bin\Debug\arith.exe'
And F# Interactive correctly finds arith.exe reporting the correct absolute path.
> open Main
> eval "true;" ;;
true
val it : unit = ()
This confirms that arith.exe was correctly found, loaded and works.
So how did F# Interactive #I command know the project path since the current directory is of no help?
What I am really after is from within F# Interactive how does one get the path to the project, E:\<directories>\fsharp-tapl\arith.
EDIT
> printfn __SOURCE_DIRECTORY__;;
E:\<directories>\fsharp-tapl\arith
val it : unit = ()
In F# Interactive, the default directory to search is the source directory. You can query it easily using __SOURCE_DIRECTORY__.
This behaviour is very convenient to allow you to use relative paths. You often have fsx files in the same folder with fs files.
#load "Ast.fs"
#load "Core.fs"
When your refer to a relative path, F# Interactive will always use the implicit source directory as the starting point.
#I ".."
#r ... // Reference some dll in parent folder of source directory
#I ".."
#r ... // Reference some dll in that folder again
If you want to remember the old directory for next reference, you should use #cd instead:
#cd "bin"
#r ... // Reference some dll in bin
#cd "Debug"
#r ... // Reference some dll in bin/Debug

Compiling Z3 on a OSX

I am trying to compile Z3 version 4.1.2. AFter a successful configuration, when you do "make", I get the following error:
Makefile:151: lib.srcs: No such file or directory
Makefile:152: shell.srcs: No such file or directory
Makefile:153: test.srcs: No such file or directory
Making test.srcs...
/usr/local/bin/dos2unix takes only stdin and stdout
make: *** [test.srcs] Error 1
I think the problem is that all textual files in z3-src-4.1.2.zip use "carriage return" (cr) and "line feed" (lf) for encoding line termination. The zip was created on a Windows machine. Another problem is the "dos2unix" application. It is an application that converts windows/dos textual files into unix/linux/osx textual files. It is a very simple application. It just replaces cr/lf with a lf.
On Linux, this application takes a single argument: the file name to be modified.
I'm currently working on a new build system that avoids this issues. In the meantime, here a some workarounds.
1) Use git to retrieve the source. git will take care of the cr/lf vs lf issue.
Here is the command for retrieving Z3:
git clone https://git01.codeplex.com/z3
If you do that, you don't need to use dos2unix.
So, you can remove the lines #$(DOS2UNIX) in Makefile.in. Another option is to replace
DOS2UNIX=#D2U#
with
DOS2UNIX=touch
in the beginning of Makefile.in
After these changes, you should be able to compile it on OSX. I successfully compiled it on OSX 10.7.
2) Get the "unstable" branch.
http://z3.codeplex.com/SourceControl/changeset/view/946a06cddbe4
This is the current "working branch". It contains the new build system. It is not ready, but it is good enough to generate the Z3 executable. Here are the instructions to build Z3 using this branch
Download the code from the page above. Or use git to retrieve the "unstable" branch. Then, execute
autoconf
./configure
python scripts/mk_make.py
cd build
make
I managed to compile it on OSX 10.7 last Friday.
3) Keep the .zip, but convert all textual files. I'm using the following python script to convert all files in the new build system. If you execute this python script in the Z3 root directory, it will convert all files.
import os
import glob
import re
import getopt
import sys
import shutil
def is_cr_lf(fname):
# Check whether text files use cr/lf
f = open(fname, 'r')
line = f.readline()
sz = len(line)
return sz >= 2 and line[sz-2] == '\r' and line[sz-1] == '\n'
# dos2unix in python
# cr/lf --> lf
def dos2unix(fname):
if is_cr_lf(fname):
fin = open(fname, 'r')
fname_new = '%s.new' % fname
fout = open(fname_new, 'w')
for line in fin:
line = line.rstrip('\r\n')
fout.write(line)
fout.write('\n')
fin.close()
fout.close()
shutil.move(fname_new, fname)
if is_verbose():
print "dos2unix '%s'" % fname
def dos2unix_tree_core(pattern, dir, files):
for filename in files:
if fnmatch(filename, pattern):
fname = os.path.join(dir, filename)
if not os.path.isdir(fname):
dos2unix(fname)
def dos2unix_tree():
os.path.walk('.', dos2unix_tree_core, '*')
dos2unix_tree()

Find files in project/solution that no longer exist

Visual Studio 2010 has a bug (or annoying behavior) that it always starts a new build for a project if it includes a reference to a (source) file that no longer exists (and subsequently all depending projects). Now I have a rather large project and the only way I know of to find such files is to manually open every file.
Is there an easier way to identify such invalid references in project files?
I wrote a python script that identifies missing files and prints them to the console.
import os
import re
import sys
def show_help():
print()
print("Syntax:", sys.argv[0], "[filename]")
print()
def check_missing_project_includes(filename):
f = open(filename, 'r')
p = re.compile('(ClCompile|ClInclude) Include="(.*?)" />', re.IGNORECASE)
missing_files = []
for line in f:
m = re.search(p, line)
if m:
filename = m.group(2)
if not os.path.exists(filename):
missing_files.append(filename)
return missing_files
if len(sys.argv) != 2:
show_help()
exit()
filename = sys.argv[1]
missing_files = check_missing_project_includes(filename)
if len(missing_files) > 0:
print("Missing files:")
for mf in missing_files:
print("\t", mf)
A technique that I've used to diagnose missing files is to install a SCC provider Addin (eg AnkhSVN if you're using Subversion), then in the Solution Explorer missing files will have a different icon. This isn't as useful for larger projects, but for smaller ones it's quite quick to see at a glance.
Have you tried opening the proj file in an editor like Notepad++ and locate and remove the references from there? (If I'm understanding the question correctly that is)

"Tabify" all files in Visual Studio solution?

There's a "tabify" command in
Edit > Advanced > Tabify Selected Lines
(and the Power Tools 2010 also provide this functionality on a per-file basis) but is there a way to do this for all code files in a solution?
ReSharper has a Clean Up command but the only half-suitable option I found there is to run formatting on all files which does more than I want (I don't want to run a complete formatting, just tabifying).
If you have added the Microsoft Productivity Power tools extension (which if you haven't I would recommned) it adds an option to tabify files. This does not apply across all files in a solution, but it's prompted for when editing each file, on a per file basis. Not quite what you're after but a help.
Also you might try setting your IDE editor settings to use tabs, then do menu-edit-advanced-format document (CTRL+E,D). This will replace groups of tab length spaces with a tab, and that should be scriptable for all files in the solution via a macro.
The request contains links to IDE macros that can do the job:
http://blogs.msdn.com/b/kevinpilchbisson/archive/2004/05/17/133371.aspx
http://web.archive.org/web/20090217094033/http://chriseargle.com/post/Format-Solution.aspx
Here is sample code for a Visual Studio macro that automatically formats all *.cs, *.h, *.cpp, and *.hpp files in an open solution, which includes converting spaces to tabs (depending on your Tab settings in Tools > Options > Text Editor > specific language or "All Languages" > Tabs):
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Public Module ConvertTabsToSpaces
Public Sub FormatSolution()
Dim sol As Solution = DTE.Solution
For i As Integer = 1 To sol.Projects.Count
FormatProject(sol.Projects.Item(i))
Next
End Sub
Private Sub FormatProject(ByVal proj As Project)
If Not proj.ProjectItems Is Nothing Then
For i As Integer = 1 To proj.ProjectItems.Count
FormatProjectItem(proj.ProjectItems.Item(i))
Next
End If
End Sub
Private Sub FormatProjectItem(ByVal projectItem As ProjectItem)
If projectItem.Kind = Constants.vsProjectItemKindPhysicalFile Then
If projectItem.Name.LastIndexOf(".cs") = projectItem.Name.Length - 3 Then
Dim window As Window = projectItem.Open(Constants.vsViewKindCode)
window.Activate()
projectItem.Document.DTE.ExecuteCommand("Edit.FormatDocument")
window.Close(vsSaveChanges.vsSaveChangesYes)
ElseIf ((projectItem.Name.LastIndexOf(".cpp") = projectItem.Name.Length - 4) OrElse (projectItem.Name.LastIndexOf(".hpp") = projectItem.Name.Length - 4) OrElse (projectItem.Name.LastIndexOf(".h") = projectItem.Name.Length - 2)) Then
Dim window As Window = projectItem.Open(Constants.vsViewKindCode)
window.Activate()
projectItem.Document.DTE.ExecuteCommand("Edit.SelectAll")
projectItem.Document.DTE.ExecuteCommand("Edit.FormatSelection")
window.Close(vsSaveChanges.vsSaveChangesYes)
End If
End If
'Be sure to format all of the ProjectItems.
If Not projectItem.ProjectItems Is Nothing Then
For i As Integer = 1 To projectItem.ProjectItems.Count
FormatProjectItem(projectItem.ProjectItems.Item(i))
Next
End If
'Format the SubProject if it exists.
If Not projectItem.SubProject Is Nothing Then
FormatProject(projectItem.SubProject)
End If
End Sub
End Module
Instructions (Visual Studio 2005, but similar for newer versions):
Launch Visual Studio
Tools > Macros > Macros IDE...
Right-click MyMacros > Add > Add New Item...
Select Module
Enter "ConvertSpacesToTabs" without quotes in the Name field
Click Add
Replace the contents of the new module with the code above
Click Save
Close the Macros IDE
Tools > Macros > Macro Explorer
Expand MyMacros > ConvertSpacesToTabs
Double-click on FormatSolution
Wait for the macro to finish
Edit
I updated the code to also support *.h, *.cpp, and *.hpp files using code from Siegmund Frenzel here:
https://stackoverflow.com/a/14766393/90287
as far as I know what "Tabify" does is this - it only replaces " " (4 spaces) with a tab, it does not change the formatting or anything else.
Although I would suggest using document formatting, the "tabification" could easily be done via a custom application which would mimic the same action on all the files that you want.
Hope this helps!
For vs2010, you can use the following find and replace (this example is for tabs to 4 spaces).
In the find box, enter: ^{ *} (^{ space *} tab)
In the replace box, enter \1 (\1 space space space space)
Check the condition box and set to regular expressions.
Newer versions of vs use different regular expression syntax, but the same should be doable.
Update
This worked by executing once for vb files, but required multiple passes for a resx file, so you may have to execute multiple times depending on the file type...
There's a new way using the dotnet CLI:
Install dotnet format by running the following command:
dotnet tool install -g dotnet-format
Run it, replacing SolutionFile.sln with the path to your solution file, with the following command line:
dotnet format SolutionFile.sln
The indent_style of .editorconfig will be used to determine if the code will use tabs or spaces.
Macros have been removed from Visual Studio 2013 onwards (and the new version of Macros uses JavaScript rather than VBScript), so to get Rami A.'s answer to work in Visual Studio 2019:
Download and install the Visual Commander extension
Extensions > VCmd > Edit macro
Name it
Paste the following code. I have had to make some changes to it to make the code work with Visual Commander. I have also changed the file extensions that it tabifies to .cs, .aspx and .ascx so change these if you need C++/other file extensions.
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports Microsoft.VisualStudio.Shell
Imports VisualCommanderExt
Public Class ConvertTabsToSpaces
Implements ICommand
Sub Run(DTE As DTE2, package As Package) Implements ICommand.Run
Dim sol As Solution = dte.Solution
For i As Integer = 1 To sol.Projects.Count
FormatProject(sol.Projects.Item(i))
Next
End Sub
Private Sub FormatProject(ByVal proj As Project)
If Not proj.ProjectItems Is Nothing Then
For i As Integer = 1 To proj.ProjectItems.Count
FormatProjectItem(proj.ProjectItems.Item(i))
Next
End If
End Sub
Private Sub FormatProjectItem(ByVal projectItem As ProjectItem)
If projectItem.Kind = Constants.vsProjectItemKindPhysicalFile Then
If (projectItem.Name.LastIndexOf(".cs") = projectItem.Name.Length - 3 OrElse (projectItem.Name.LastIndexOf(".aspx") = projectItem.Name.Length - 5 OrElse (projectItem.Name.LastIndexOf(".ascx") = projectItem.Name.Length - 5))) Then
Dim window As Window = projectItem.Open(Constants.vsViewKindCode)
window.Activate()
Try
projectItem.Document.DTE.ExecuteCommand("Edit.RemoveAndSort")
Catch
' Do nothing
End Try
Try
projectItem.Document.DTE.ExecuteCommand("Edit.SelectAll")
projectItem.Document.DTE.ExecuteCommand("Edit.FormatSelection")
Catch
' Do nothing
End Try
window.Close(vsSaveChanges.vsSaveChangesYes)
End If
End If
'Be sure to format all of the ProjectItems
If Not projectItem.ProjectItems Is Nothing Then
For i As Integer = 1 To projectItem.ProjectItems.Count
FormatProjectItem(projectItem.ProjectItems.Item(i))
Next
End If
'Format the SubProject if it exists
If Not projectItem.SubProject Is Nothing Then
FormatProject(projectItem.SubProject)
End If
End Sub
End Class
Save
Run
To save for future use: Extensions > VCmd > Save macro as command > Name it > Save

Resources