@matheusbsbs / matheus-bagliano / commits / 259d87c354
Fork 0

Add scripts to generate projects for other buildsystems (MSVC vcproj, QMake)

These scripts generate projects for the MSVC IDE (.vcproj files) or QMake (.pro files), based on the output of a 'make -n MSVC=1 V=1' run. This enables us to simply do the necesarry changes in the Makefile, and you can update the other buildsystems by regenerating the files. Keeping the other buildsystems up-to-date with main development. The generator system is designed to easily drop in pm's for other buildsystems as well, if someone has an itch. However, the focus has been Windows development, so the 'engine' might need patches to support any platform. Also add some .gitignore entries for MSVC files. Signed-off-by: Marius Storm-Olsen <mstormo@gmail.com> Acked-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Marius Storm-Olsen committed Sep 16, 2009 at 10:20 UTC 259d87c354954e8ee3b241dce1393c27186e8ee7
8 files changed +1503 -1
.gitignore
+11
@@ -179,3 +179,14 @@ configure
179 tags
180 TAGS
181 cscope*
182 +*.obj
183 +*.lib
184 +*.sln
185 +*.suo
186 +*.ncb
187 +*.vcproj
188 +*.user
189 +*.idb
190 +*.pdb
191 +Debug/
192 +Release/
compat/vcbuild/README
+12 -1
@@ -33,7 +33,18 @@ The Steps of Build Git with VS2008
33 make common-cmds.h
34 to generate the common-cmds.h file needed to compile git.
35
36 -4. Then build Git with the GNU Make Makefile in the Git projects root
36 +4. Then either build Git with the GNU Make Makefile in the Git projects
37 + root
38 make MSVC=1
39 + or generate Visual Studio solution/projects (.sln/.vcproj) with the
40 + command
41 + perl contrib/buildsystems/generate -g Vcproj
42 + and open and build the solution with the IDE
43 + devenv git.sln /useenv
44 + or build with the IDE build engine directly from the command line
45 + devenv git.sln /useenv /build "Release|Win32"
46 + The /useenv option is required, so Visual Studio picks up the
47 + environment variables for the support libraries required to build
48 + Git, which you set up in step 1.
49
50 Done!
contrib/buildsystems/Generators.pm new
+42
@@ -0,0 +1,42 @@
1 +package Generators;
2 +require Exporter;
3 +
4 +use strict;
5 +use File::Basename;
6 +no strict 'refs';
7 +use vars qw($VERSION @AVAILABLE);
8 +
9 +our $VERSION = '1.00';
10 +our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE);
11 +@ISA = qw(Exporter);
12 +
13 +BEGIN {
14 + local(*D);
15 + my $me = $INC{"Generators.pm"};
16 + die "Couldn't find myself in \@INC, which is required to load the generators!" if ("$me" eq "");
17 + $me = dirname($me);
18 + if (opendir(D,"$me/Generators")) {
19 + foreach my $gen (readdir(D)) {
20 + next if ($gen =~ /^\.\.?$/);
21 + require "${me}/Generators/$gen";
22 + $gen =~ s,\.pm,,;
23 + push(@AVAILABLE, $gen);
24 + }
25 + closedir(D);
26 + my $gens = join(', ', @AVAILABLE);
27 + }
28 +
29 + push @EXPORT_OK, qw(available);
30 +}
31 +
32 +sub available {
33 + return @AVAILABLE;
34 +}
35 +
36 +sub generate {
37 + my ($gen, $git_dir, $out_dir, $rel_dir, %build_structure) = @_;
38 + return eval("Generators::${gen}::generate(\$git_dir, \$out_dir, \$rel_dir, \%build_structure)") if grep(/^$gen$/, @AVAILABLE);
39 + die "Generator \"${gen}\" is not available!\nAvailable generators are: @AVAILABLE\n";
40 +}
41 +
42 +1;
contrib/buildsystems/Generators/QMake.pm new
+189
@@ -0,0 +1,189 @@
1 +package Generators::QMake;
2 +require Exporter;
3 +
4 +use strict;
5 +use vars qw($VERSION);
6 +
7 +our $VERSION = '1.00';
8 +our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE);
9 +@ISA = qw(Exporter);
10 +
11 +BEGIN {
12 + push @EXPORT_OK, qw(generate);
13 +}
14 +
15 +sub generate {
16 + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
17 +
18 + my @libs = @{$build_structure{"LIBS"}};
19 + foreach (@libs) {
20 + createLibProject($_, $git_dir, $out_dir, $rel_dir, %build_structure);
21 + }
22 +
23 + my @apps = @{$build_structure{"APPS"}};
24 + foreach (@apps) {
25 + createAppProject($_, $git_dir, $out_dir, $rel_dir, %build_structure);
26 + }
27 +
28 + createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure);
29 + return 0;
30 +}
31 +
32 +sub createLibProject {
33 + my ($libname, $git_dir, $out_dir, $rel_dir, %build_structure) = @_;
34 + print "Generate $libname lib project\n";
35 + $rel_dir = "../$rel_dir";
36 +
37 + my $sources = join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"LIBS_${libname}_SOURCES"}})));
38 + my $defines = join(" \\\n\t", sort(@{$build_structure{"LIBS_${libname}_DEFINES"}}));
39 + my $includes= join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"LIBS_${libname}_INCLUDES"}})));
40 + my $cflags = join(" ", sort(@{$build_structure{"LIBS_${libname}_CFLAGS"}}));
41 +
42 + my $cflags_debug = $cflags;
43 + $cflags_debug =~ s/-MT/-MTd/;
44 + $cflags_debug =~ s/-O.//;
45 +
46 + my $cflags_release = $cflags;
47 + $cflags_release =~ s/-MTd/-MT/;
48 +
49 + my @tmp = @{$build_structure{"LIBS_${libname}_LFLAGS"}};
50 + my @tmp2 = ();
51 + foreach (@tmp) {
52 + if (/^-LTCG/) {
53 + } elsif (/^-L/) {
54 + $_ =~ s/^-L/-LIBPATH:$rel_dir\//;
55 + }
56 + push(@tmp2, $_);
57 + }
58 + my $lflags = join(" ", sort(@tmp));
59 +
60 + my $target = $libname;
61 + $target =~ s/\//_/g;
62 + $defines =~ s/-D//g;
63 + $defines =~ s/"/\\\\"/g;
64 + $includes =~ s/-I//g;
65 + mkdir "$target" || die "Could not create the directory $target for lib project!\n";
66 + open F, ">$target/$target.pro" || die "Could not open $target/$target.pro for writing!\n";
67 + print F << "EOM";
68 +TEMPLATE = lib
69 +TARGET = $target
70 +DESTDIR = $rel_dir
71 +
72 +CONFIG -= qt
73 +CONFIG += static
74 +
75 +QMAKE_CFLAGS =
76 +QMAKE_CFLAGS_RELEASE = $cflags_release
77 +QMAKE_CFLAGS_DEBUG = $cflags_debug
78 +QMAKE_LIBFLAGS = $lflags
79 +
80 +DEFINES += \\
81 + $defines
82 +
83 +INCLUDEPATH += \\
84 + $includes
85 +
86 +SOURCES += \\
87 + $sources
88 +EOM
89 + close F;
90 +}
91 +
92 +sub createAppProject {
93 + my ($appname, $git_dir, $out_dir, $rel_dir, %build_structure) = @_;
94 + print "Generate $appname app project\n";
95 + $rel_dir = "../$rel_dir";
96 +
97 + my $sources = join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"APPS_${appname}_SOURCES"}})));
98 + my $defines = join(" \\\n\t", sort(@{$build_structure{"APPS_${appname}_DEFINES"}}));
99 + my $includes= join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"APPS_${appname}_INCLUDES"}})));
100 + my $cflags = join(" ", sort(@{$build_structure{"APPS_${appname}_CFLAGS"}}));
101 +
102 + my $cflags_debug = $cflags;
103 + $cflags_debug =~ s/-MT/-MTd/;
104 + $cflags_debug =~ s/-O.//;
105 +
106 + my $cflags_release = $cflags;
107 + $cflags_release =~ s/-MTd/-MT/;
108 +
109 + my $libs;
110 + foreach (sort(@{$build_structure{"APPS_${appname}_LIBS"}})) {
111 + $_ =~ s/\//_/g;
112 + $libs .= " $_";
113 + }
114 + my @tmp = @{$build_structure{"APPS_${appname}_LFLAGS"}};
115 + my @tmp2 = ();
116 + foreach (@tmp) {
117 + # next if ($_ eq "-NODEFAULTLIB:MSVCRT.lib");
118 + if (/^-LTCG/) {
119 + } elsif (/^-L/) {
120 + $_ =~ s/^-L/-LIBPATH:$rel_dir\//;
121 + }
122 + push(@tmp2, $_);
123 + }
124 + my $lflags = join(" ", sort(@tmp));
125 +
126 + my $target = $appname;
127 + $target =~ s/\.exe//;
128 + $target =~ s/\//_/g;
129 + $defines =~ s/-D//g;
130 + $defines =~ s/"/\\\\"/g;
131 + $includes =~ s/-I//g;
132 + mkdir "$target" || die "Could not create the directory $target for app project!\n";
133 + open F, ">$target/$target.pro" || die "Could not open $target/$target.pro for writing!\n";
134 + print F << "EOM";
135 +TEMPLATE = app
136 +TARGET = $target
137 +DESTDIR = $rel_dir
138 +
139 +CONFIG -= qt embed_manifest_exe
140 +CONFIG += console
141 +
142 +QMAKE_CFLAGS =
143 +QMAKE_CFLAGS_RELEASE = $cflags_release
144 +QMAKE_CFLAGS_DEBUG = $cflags_debug
145 +QMAKE_LFLAGS = $lflags
146 +LIBS = $libs
147 +
148 +DEFINES += \\
149 + $defines
150 +
151 +INCLUDEPATH += \\
152 + $includes
153 +
154 +win32:QMAKE_LFLAGS += -LIBPATH:$rel_dir
155 +else: QMAKE_LFLAGS += -L$rel_dir
156 +
157 +SOURCES += \\
158 + $sources
159 +EOM
160 + close F;
161 +}
162 +
163 +sub createGlueProject {
164 + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
165 + my $libs = join(" \\ \n", map("\t$_|$_.pro", @{$build_structure{"LIBS"}}));
166 + my $apps = join(" \\ \n", map("\t$_|$_.pro", @{$build_structure{"APPS"}}));
167 + $libs =~ s/\.a//g;
168 + $libs =~ s/\//_/g;
169 + $libs =~ s/\|/\//g;
170 + $apps =~ s/\.exe//g;
171 + $apps =~ s/\//_/g;
172 + $apps =~ s/\|/\//g;
173 +
174 + my $filename = $out_dir;
175 + $filename =~ s/.*\/([^\/]+)$/$1/;
176 + $filename =~ s/\/$//;
177 + print "Generate glue project $filename.pro\n";
178 + open F, ">$filename.pro" || die "Could not open $filename.pro for writing!\n";
179 + print F << "EOM";
180 +TEMPLATE = subdirs
181 +CONFIG += ordered
182 +SUBDIRS += \\
183 +$libs \\
184 +$apps
185 +EOM
186 + close F;
187 +}
188 +
189 +1;
contrib/buildsystems/Generators/Vcproj.pm new
+639
@@ -0,0 +1,639 @@
1 +package Generators::Vcproj;
2 +require Exporter;
3 +
4 +use strict;
5 +use vars qw($VERSION);
6 +
7 +our $VERSION = '1.00';
8 +our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE);
9 +@ISA = qw(Exporter);
10 +
11 +BEGIN {
12 + push @EXPORT_OK, qw(generate);
13 +}
14 +
15 +my $guid_index = 0;
16 +my @GUIDS = (
17 + "{E07B9989-2BF7-4F21-8918-BE22BA467AC3}",
18 + "{278FFB51-0296-4A44-A81A-22B87B7C3592}",
19 + "{7346A2C4-F0FD-444F-9EBE-1AF23B2B5650}",
20 + "{67F421AC-EB34-4D49-820B-3196807B423F}",
21 + "{385DCFE1-CC8C-4211-A451-80FCFC31CA51}",
22 + "{97CC46C5-D2CC-4D26-B634-E75792B79916}",
23 + "{C7CE21FE-6EF8-4012-A5C7-A22BCEDFBA11}",
24 + "{51575134-3FDF-42D1-BABD-3FB12669C6C9}",
25 + "{0AE195E4-9823-4B87-8E6F-20C5614AF2FF}",
26 + "{4B918255-67CA-43BB-A46C-26704B666E6B}",
27 + "{18CCFEEF-C8EE-4CC1-A265-26F95C9F4649}",
28 + "{5D5D90FA-01B7-4973-AFE5-CA88C53AC197}",
29 + "{1F054320-036D-49E1-B384-FB5DF0BC8AC0}",
30 + "{7CED65EE-F2D9-4171-825B-C7D561FE5786}",
31 + "{8D341679-0F07-4664-9A56-3BA0DE88B9BC}",
32 + "{C189FEDC-2957-4BD7-9FA4-7622241EA145}",
33 + "{66844203-1B9F-4C53-9274-164FFF95B847}",
34 + "{E4FEA145-DECC-440D-AEEA-598CF381FD43}",
35 + "{73300A8E-C8AC-41B0-B555-4F596B681BA7}",
36 + "{873FDEB1-D01D-40BF-A1BF-8BBC58EC0F51}",
37 + "{7922C8BE-76C5-4AC6-8BF7-885C0F93B782}",
38 + "{E245D370-308B-4A49-BFC1-1E527827975F}",
39 + "{F6FA957B-66FC-4ED7-B260-E59BBE4FE813}",
40 + "{E6055070-0198-431A-BC49-8DB6CEE770AE}",
41 + "{54159234-C3EB-43DA-906B-CE5DA5C74654}",
42 + "{594CFC35-0B60-46F6-B8EF-9983ACC1187D}",
43 + "{D93FCAB7-1F01-48D2-B832-F761B83231A5}",
44 + "{DBA5E6AC-E7BE-42D3-8703-4E787141526E}",
45 + "{6171953F-DD26-44C7-A3BE-CC45F86FC11F}",
46 + "{9E19DDBE-F5E4-4A26-A2FE-0616E04879B8}",
47 + "{AE81A615-99E3-4885-9CE0-D9CAA193E867}",
48 + "{FBF4067E-1855-4F6C-8BCD-4D62E801A04D}",
49 + "{17007948-6593-4AEB-8106-F7884B4F2C19}",
50 + "{199D4C8D-8639-4DA6-82EF-08668C35DEE0}",
51 + "{E085E50E-C140-4CF3-BE4B-094B14F0DDD6}",
52 + "{00785268-A9CC-4E40-AC29-BAC0019159CE}",
53 + "{4C06F56A-DCDB-46A6-B67C-02339935CF12}",
54 + "{3A62D3FD-519E-4EC9-8171-D2C1BFEA022F}",
55 + "{3A62D3FD-519E-4EC9-8171-D2C1BFEA022F}",
56 + "{9392EB58-D7BA-410B-B1F0-B2FAA6BC89A7}",
57 + "{2ACAB2D5-E0CE-4027-BCA0-D78B2D7A6C66}",
58 + "{86E216C3-43CE-481A-BCB2-BE5E62850635}",
59 + "{FB631291-7923-4B91-9A57-7B18FDBB7A42}",
60 + "{0A176EC9-E934-45B8-B87F-16C7F4C80039}",
61 + "{DF55CA80-46E8-4C53-B65B-4990A23DD444}",
62 + "{3A0F9895-55D2-4710-BE5E-AD7498B5BF44}",
63 + "{294BDC5A-F448-48B6-8110-DD0A81820F8C}",
64 + "{4B9F66E9-FAC9-47AB-B1EF-C16756FBFD06}",
65 + "{72EA49C6-2806-48BD-B81B-D4905102E19C}",
66 + "{5728EB7E-8929-486C-8CD5-3238D060E768}"
67 +);
68 +
69 +sub generate {
70 + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
71 + my @libs = @{$build_structure{"LIBS"}};
72 + foreach (@libs) {
73 + createLibProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure);
74 + }
75 +
76 + my @apps = @{$build_structure{"APPS"}};
77 + foreach (@apps) {
78 + createAppProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure);
79 + }
80 +
81 + createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure);
82 + return 0;
83 +}
84 +
85 +sub createLibProject {
86 + my ($libname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_;
87 + print "Generate $libname vcproj lib project\n";
88 + $rel_dir = "..\\$rel_dir";
89 + $rel_dir =~ s/\//\\/g;
90 +
91 + my $target = $libname;
92 + $target =~ s/\//_/g;
93 + $target =~ s/\.a//;
94 +
95 + my $uuid = $GUIDS[$guid_index];
96 + $$build_structure{"LIBS_${target}_GUID"} = $uuid;
97 + $guid_index += 1;
98 +
99 + my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"LIBS_${libname}_SOURCES"}}));
100 + my @sources;
101 + foreach (@srcs) {
102 + $_ =~ s/\//\\/g;
103 + push(@sources, $_);
104 + }
105 + my $defines = join(",", sort(@{$$build_structure{"LIBS_${libname}_DEFINES"}}));
106 + my $includes= join(";", sort(map("&quot;$rel_dir\\$_&quot;", @{$$build_structure{"LIBS_${libname}_INCLUDES"}})));
107 + my $cflags = join(" ", sort(@{$$build_structure{"LIBS_${libname}_CFLAGS"}}));
108 + $cflags =~ s/\"/&quot;/g;
109 +
110 + my $cflags_debug = $cflags;
111 + $cflags_debug =~ s/-MT/-MTd/;
112 + $cflags_debug =~ s/-O.//;
113 +
114 + my $cflags_release = $cflags;
115 + $cflags_release =~ s/-MTd/-MT/;
116 +
117 + my @tmp = @{$$build_structure{"LIBS_${libname}_LFLAGS"}};
118 + my @tmp2 = ();
119 + foreach (@tmp) {
120 + if (/^-LTCG/) {
121 + } elsif (/^-L/) {
122 + $_ =~ s/^-L/-LIBPATH:$rel_dir\//;
123 + }
124 + push(@tmp2, $_);
125 + }
126 + my $lflags = join(" ", sort(@tmp));
127 +
128 + $defines =~ s/-D//g;
129 + $defines =~ s/\"/\\&quot;/g;
130 + $defines =~ s/\'//g;
131 + $includes =~ s/-I//g;
132 + mkdir "$target" || die "Could not create the directory $target for lib project!\n";
133 + open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n";
134 + print F << "EOM";
135 +<?xml version="1.0" encoding = "Windows-1252"?>
136 +<VisualStudioProject
137 + ProjectType="Visual C++"
138 + Version="9,00"
139 + Name="$target"
140 + ProjectGUID="$uuid">
141 + <Platforms>
142 + <Platform
143 + Name="Win32"/>
144 + </Platforms>
145 + <ToolFiles>
146 + </ToolFiles>
147 + <Configurations>
148 + <Configuration
149 + Name="Debug|Win32"
150 + OutputDirectory="$rel_dir"
151 + ConfigurationType="4"
152 + CharacterSet="0"
153 + IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
154 + >
155 + <Tool
156 + Name="VCPreBuildEventTool"
157 + />
158 + <Tool
159 + Name="VCCustomBuildTool"
160 + />
161 + <Tool
162 + Name="VCXMLDataGeneratorTool"
163 + />
164 + <Tool
165 + Name="VCWebServiceProxyGeneratorTool"
166 + />
167 + <Tool
168 + Name="VCMIDLTool"
169 + />
170 + <Tool
171 + Name="VCCLCompilerTool"
172 + AdditionalOptions="$cflags_debug"
173 + Optimization="0"
174 + InlineFunctionExpansion="1"
175 + AdditionalIncludeDirectories="$includes"
176 + PreprocessorDefinitions="UNICODE,WIN32,_DEBUG,$defines"
177 + MinimalRebuild="true"
178 + RuntimeLibrary="1"
179 + UsePrecompiledHeader="0"
180 + WarningLevel="3"
181 + DebugInformationFormat="3"
182 + />
183 + <Tool
184 + Name="VCManagedResourceCompilerTool"
185 + />
186 + <Tool
187 + Name="VCResourceCompilerTool"
188 + />
189 + <Tool
190 + Name="VCPreLinkEventTool"
191 + />
192 + <Tool
193 + Name="VCLibrarianTool"
194 + SuppressStartupBanner="true"
195 + />
196 + <Tool
197 + Name="VCALinkTool"
198 + />
199 + <Tool
200 + Name="VCXDCMakeTool"
201 + />
202 + <Tool
203 + Name="VCBscMakeTool"
204 + />
205 + <Tool
206 + Name="VCFxCopTool"
207 + />
208 + <Tool
209 + Name="VCPostBuildEventTool"
210 + />
211 + </Configuration>
212 + <Configuration
213 + Name="Release|Win32"
214 + OutputDirectory="$rel_dir"
215 + ConfigurationType="4"
216 + CharacterSet="0"
217 + WholeProgramOptimization="1"
218 + IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
219 + >
220 + <Tool
221 + Name="VCPreBuildEventTool"
222 + />
223 + <Tool
224 + Name="VCCustomBuildTool"
225 + />
226 + <Tool
227 + Name="VCXMLDataGeneratorTool"
228 + />
229 + <Tool
230 + Name="VCWebServiceProxyGeneratorTool"
231 + />
232 + <Tool
233 + Name="VCMIDLTool"
234 + />
235 + <Tool
236 + Name="VCCLCompilerTool"
237 + AdditionalOptions="$cflags_release"
238 + Optimization="2"
239 + InlineFunctionExpansion="1"
240 + EnableIntrinsicFunctions="true"
241 + AdditionalIncludeDirectories="$includes"
242 + PreprocessorDefinitions="UNICODE,WIN32,NDEBUG,$defines"
243 + RuntimeLibrary="0"
244 + EnableFunctionLevelLinking="true"
245 + UsePrecompiledHeader="0"
246 + WarningLevel="3"
247 + DebugInformationFormat="3"
248 + />
249 + <Tool
250 + Name="VCManagedResourceCompilerTool"
251 + />
252 + <Tool
253 + Name="VCResourceCompilerTool"
254 + />
255 + <Tool
256 + Name="VCPreLinkEventTool"
257 + />
258 + <Tool
259 + Name="VCLibrarianTool"
260 + SuppressStartupBanner="true"
261 + />
262 + <Tool
263 + Name="VCALinkTool"
264 + />
265 + <Tool
266 + Name="VCXDCMakeTool"
267 + />
268 + <Tool
269 + Name="VCBscMakeTool"
270 + />
271 + <Tool
272 + Name="VCFxCopTool"
273 + />
274 + <Tool
275 + Name="VCPostBuildEventTool"
276 + />
277 + </Configuration>
278 + </Configurations>
279 + <Files>
280 + <Filter
281 + Name="Source Files"
282 + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
283 + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
284 +EOM
285 + foreach(@sources) {
286 + print F << "EOM";
287 + <File
288 + RelativePath="$_"/>
289 +EOM
290 + }
291 + print F << "EOM";
292 + </Filter>
293 + </Files>
294 + <Globals>
295 + </Globals>
296 +</VisualStudioProject>
297 +EOM
298 + close F;
299 +}
300 +
301 +sub createAppProject {
302 + my ($appname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_;
303 + print "Generate $appname vcproj app project\n";
304 + $rel_dir = "..\\$rel_dir";
305 + $rel_dir =~ s/\//\\/g;
306 +
307 + my $target = $appname;
308 + $target =~ s/\//_/g;
309 + $target =~ s/\.exe//;
310 +
311 + my $uuid = $GUIDS[$guid_index];
312 + $$build_structure{"APPS_${target}_GUID"} = $uuid;
313 + $guid_index += 1;
314 +
315 + my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"APPS_${appname}_SOURCES"}}));
316 + my @sources;
317 + foreach (@srcs) {
318 + $_ =~ s/\//\\/g;
319 + push(@sources, $_);
320 + }
321 + my $defines = join(",", sort(@{$$build_structure{"APPS_${appname}_DEFINES"}}));
322 + my $includes= join(";", sort(map("&quot;$rel_dir\\$_&quot;", @{$$build_structure{"APPS_${appname}_INCLUDES"}})));
323 + my $cflags = join(" ", sort(@{$$build_structure{"APPS_${appname}_CFLAGS"}}));
324 + $cflags =~ s/\"/&quot;/g;
325 +
326 + my $cflags_debug = $cflags;
327 + $cflags_debug =~ s/-MT/-MTd/;
328 + $cflags_debug =~ s/-O.//;
329 +
330 + my $cflags_release = $cflags;
331 + $cflags_release =~ s/-MTd/-MT/;
332 +
333 + my $libs;
334 + foreach (sort(@{$$build_structure{"APPS_${appname}_LIBS"}})) {
335 + $_ =~ s/\//_/g;
336 + $libs .= " $_";
337 + }
338 + my @tmp = @{$$build_structure{"APPS_${appname}_LFLAGS"}};
339 + my @tmp2 = ();
340 + foreach (@tmp) {
341 + if (/^-LTCG/) {
342 + } elsif (/^-L/) {
343 + $_ =~ s/^-L/-LIBPATH:$rel_dir\//;
344 + }
345 + push(@tmp2, $_);
346 + }
347 + my $lflags = join(" ", sort(@tmp)) . " -LIBPATH:$rel_dir";
348 +
349 + $defines =~ s/-D//g;
350 + $defines =~ s/\"/\\&quot;/g;
351 + $defines =~ s/\'//g;
352 + $defines =~ s/\\\\/\\/g;
353 + $includes =~ s/-I//g;
354 + mkdir "$target" || die "Could not create the directory $target for lib project!\n";
355 + open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n";
356 + print F << "EOM";
357 +<?xml version="1.0" encoding = "Windows-1252"?>
358 +<VisualStudioProject
359 + ProjectType="Visual C++"
360 + Version="9,00"
361 + Name="$target"
362 + ProjectGUID="$uuid">
363 + <Platforms>
364 + <Platform
365 + Name="Win32"/>
366 + </Platforms>
367 + <ToolFiles>
368 + </ToolFiles>
369 + <Configurations>
370 + <Configuration
371 + Name="Debug|Win32"
372 + OutputDirectory="$rel_dir"
373 + ConfigurationType="1"
374 + CharacterSet="0"
375 + IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
376 + >
377 + <Tool
378 + Name="VCPreBuildEventTool"
379 + />
380 + <Tool
381 + Name="VCCustomBuildTool"
382 + />
383 + <Tool
384 + Name="VCXMLDataGeneratorTool"
385 + />
386 + <Tool
387 + Name="VCWebServiceProxyGeneratorTool"
388 + />
389 + <Tool
390 + Name="VCMIDLTool"
391 + />
392 + <Tool
393 + Name="VCCLCompilerTool"
394 + AdditionalOptions="$cflags_debug"
395 + Optimization="0"
396 + InlineFunctionExpansion="1"
397 + AdditionalIncludeDirectories="$includes"
398 + PreprocessorDefinitions="UNICODE,WIN32,_DEBUG,$defines"
399 + MinimalRebuild="true"
400 + RuntimeLibrary="1"
401 + UsePrecompiledHeader="0"
402 + WarningLevel="3"
403 + DebugInformationFormat="3"
404 + />
405 + <Tool
406 + Name="VCManagedResourceCompilerTool"
407 + />
408 + <Tool
409 + Name="VCResourceCompilerTool"
410 + />
411 + <Tool
412 + Name="VCPreLinkEventTool"
413 + />
414 + <Tool
415 + Name="VCLinkerTool"
416 + AdditionalDependencies="$libs"
417 + AdditionalOptions="$lflags"
418 + LinkIncremental="2"
419 + GenerateDebugInformation="true"
420 + SubSystem="1"
421 + TargetMachine="1"
422 + />
423 + <Tool
424 + Name="VCALinkTool"
425 + />
426 + <Tool
427 + Name="VCXDCMakeTool"
428 + />
429 + <Tool
430 + Name="VCBscMakeTool"
431 + />
432 + <Tool
433 + Name="VCFxCopTool"
434 + />
435 + <Tool
436 + Name="VCPostBuildEventTool"
437 + />
438 + </Configuration>
439 + <Configuration
440 + Name="Release|Win32"
441 + OutputDirectory="$rel_dir"
442 + ConfigurationType="1"
443 + CharacterSet="0"
444 + WholeProgramOptimization="1"
445 + IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
446 + >
447 + <Tool
448 + Name="VCPreBuildEventTool"
449 + />
450 + <Tool
451 + Name="VCCustomBuildTool"
452 + />
453 + <Tool
454 + Name="VCXMLDataGeneratorTool"
455 + />
456 + <Tool
457 + Name="VCWebServiceProxyGeneratorTool"
458 + />
459 + <Tool
460 + Name="VCMIDLTool"
461 + />
462 + <Tool
463 + Name="VCCLCompilerTool"
464 + AdditionalOptions="$cflags_release"
465 + Optimization="2"
466 + InlineFunctionExpansion="1"
467 + EnableIntrinsicFunctions="true"
468 + AdditionalIncludeDirectories="$includes"
469 + PreprocessorDefinitions="UNICODE,WIN32,NDEBUG,$defines"
470 + RuntimeLibrary="0"
471 + EnableFunctionLevelLinking="true"
472 + UsePrecompiledHeader="0"
473 + WarningLevel="3"
474 + DebugInformationFormat="3"
475 + />
476 + <Tool
477 + Name="VCManagedResourceCompilerTool"
478 + />
479 + <Tool
480 + Name="VCResourceCompilerTool"
481 + />
482 + <Tool
483 + Name="VCPreLinkEventTool"
484 + />
485 + <Tool
486 + Name="VCLinkerTool"
487 + AdditionalDependencies="$libs"
488 + AdditionalOptions="$lflags"
489 + LinkIncremental="1"
490 + GenerateDebugInformation="true"
491 + SubSystem="1"
492 + TargetMachine="1"
493 + OptimizeReferences="2"
494 + EnableCOMDATFolding="2"
495 + />
496 + <Tool
497 + Name="VCALinkTool"
498 + />
499 + <Tool
500 + Name="VCXDCMakeTool"
501 + />
502 + <Tool
503 + Name="VCBscMakeTool"
504 + />
505 + <Tool
506 + Name="VCFxCopTool"
507 + />
508 + <Tool
509 + Name="VCPostBuildEventTool"
510 + />
511 + </Configuration>
512 + </Configurations>
513 + <Files>
514 + <Filter
515 + Name="Source Files"
516 + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
517 + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
518 +EOM
519 + foreach(@sources) {
520 + print F << "EOM";
521 + <File
522 + RelativePath="$_"/>
523 +EOM
524 + }
525 + print F << "EOM";
526 + </Filter>
527 + </Files>
528 + <Globals>
529 + </Globals>
530 +</VisualStudioProject>
531 +EOM
532 + close F;
533 +}
534 +
535 +sub createGlueProject {
536 + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
537 + print "Generate solutions file\n";
538 + $rel_dir = "..\\$rel_dir";
539 + $rel_dir =~ s/\//\\/g;
540 + my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 10.00\n";
541 + my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = ";
542 + my $SLN_POST = "\nEndProject\n";
543 +
544 + my @libs = @{$build_structure{"LIBS"}};
545 + my @tmp;
546 + foreach (@libs) {
547 + $_ =~ s/\//_/g;
548 + $_ =~ s/\.a//;
549 + push(@tmp, $_);
550 + }
551 + @libs = @tmp;
552 +
553 + my @apps = @{$build_structure{"APPS"}};
554 + @tmp = ();
555 + foreach (@apps) {
556 + $_ =~ s/\//_/g;
557 + $_ =~ s/\.exe//;
558 + push(@tmp, $_);
559 + }
560 + @apps = @tmp;
561 +
562 + open F, ">git.sln" || die "Could not open git.sln for writing!\n";
563 + print F "$SLN_HEAD";
564 + foreach (@libs) {
565 + my $libname = $_;
566 + my $uuid = $build_structure{"LIBS_${libname}_GUID"};
567 + print F "$SLN_PRE";
568 + print F "\"${libname}\", \"${libname}\\${libname}.vcproj\", \"${uuid}\"";
569 + print F "$SLN_POST";
570 + }
571 + foreach (@apps) {
572 + my $appname = $_;
573 + my $uuid = $build_structure{"APPS_${appname}_GUID"};
574 + print F "$SLN_PRE";
575 + print F "\"${appname}\", \"${appname}\\${appname}.vcproj\", \"${uuid}\"";
576 + print F "$SLN_POST";
577 + }
578 +
579 + print F << "EOM";
580 +Global
581 + GlobalSection(SolutionConfiguration) = preSolution
582 + ConfigName.0 = Debug|Win32
583 + ConfigName.1 = Release|Win32
584 + EndGlobalSection
585 + GlobalSection(ProjectDependencies) = postSolution
586 +EOM
587 + foreach (@{$build_structure{"APPS"}}) {
588 + my $appname = $_;
589 + my $appname_clean = $_;
590 + $appname_clean =~ s/\//_/g;
591 + $appname_clean =~ s/\.exe//;
592 +
593 + my $uuid = $build_structure{"APPS_${appname_clean}_GUID"};
594 + my $dep_index = 0;
595 + foreach(@{$build_structure{"APPS_${appname}_LIBS"}}) {
596 + my $libname = $_;
597 + $libname =~ s/\//_/g;
598 + $libname =~ s/\.(a|lib)//;
599 + my $libuuid = $build_structure{"LIBS_${libname}_GUID"};
600 + if (defined $libuuid) {
601 + print F "\t\t${uuid}.${dep_index} = ${libuuid}\n";
602 + $dep_index += 1;
603 + }
604 + }
605 + }
606 +
607 + print F << "EOM";
608 + EndGlobalSection
609 + GlobalSection(ProjectConfiguration) = postSolution
610 +EOM
611 + foreach (@libs) {
612 + my $libname = $_;
613 + my $uuid = $build_structure{"LIBS_${libname}_GUID"};
614 + print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n";
615 + print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n";
616 + print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n";
617 + print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n";
618 + }
619 + foreach (@apps) {
620 + my $appname = $_;
621 + my $uuid = $build_structure{"APPS_${appname}_GUID"};
622 + print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n";
623 + print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n";
624 + print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n";
625 + print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n";
626 + }
627 +
628 + print F << "EOM";
629 + EndGlobalSection
630 + GlobalSection(ExtensibilityGlobals) = postSolution
631 + EndGlobalSection
632 + GlobalSection(ExtensibilityAddIns) = postSolution
633 + EndGlobalSection
634 +EndGlobal
635 +EOM
636 + close F;
637 +}
638 +
639 +1;
contrib/buildsystems/engine.pl new
+353
@@ -0,0 +1,353 @@
1 +#!/usr/bin/perl -w
2 +######################################################################
3 +# Do not call this script directly!
4 +#
5 +# The generate script ensures that @INC is correct before the engine
6 +# is executed.
7 +#
8 +# Copyright (C) 2009 Marius Storm-Olsen <mstormo@gmail.com>
9 +######################################################################
10 +use strict;
11 +use File::Basename;
12 +use File::Spec;
13 +use Cwd;
14 +use Generators;
15 +
16 +my (%build_structure, %compile_options, @makedry);
17 +my $out_dir = getcwd();
18 +my $git_dir = $out_dir;
19 +$git_dir =~ s=\\=/=g;
20 +$git_dir = dirname($git_dir) while (!-e "$git_dir/git.c" && "$git_dir" ne "");
21 +die "Couldn't find Git repo" if ("$git_dir" eq "");
22 +
23 +my @gens = Generators::available();
24 +my $gen = "Vcproj";
25 +
26 +sub showUsage
27 +{
28 + my $genlist = join(', ', @gens);
29 + print << "EOM";
30 +generate usage:
31 + -g <GENERATOR> --gen <GENERATOR> Specify the buildsystem generator (default: $gen)
32 + Available: $genlist
33 + -o <PATH> --out <PATH> Specify output directory generation (default: .)
34 + -i <FILE> --in <FILE> Specify input file, instead of running GNU Make
35 + -h,-? --help This help
36 +EOM
37 + exit 0;
38 +}
39 +
40 +# Parse command-line options
41 +while (@ARGV) {
42 + my $arg = shift @ARGV;
43 + if ("$arg" eq "-h" || "$arg" eq "--help" || "$arg" eq "-?") {
44 + showUsage();
45 + exit(0);
46 + } elsif("$arg" eq "--out" || "$arg" eq "-o") {
47 + $out_dir = shift @ARGV;
48 + } elsif("$arg" eq "--gen" || "$arg" eq "-g") {
49 + $gen = shift @ARGV;
50 + } elsif("$arg" eq "--in" || "$arg" eq "-i") {
51 + my $infile = shift @ARGV;
52 + open(F, "<$infile") || die "Couldn't open file $infile";
53 + @makedry = <F>;
54 + close(F);
55 + }
56 +}
57 +
58 +# NOT using File::Spec->rel2abs($path, $base) here, as
59 +# it fails badly for me in the msysgit environment
60 +$git_dir = File::Spec->rel2abs($git_dir);
61 +$out_dir = File::Spec->rel2abs($out_dir);
62 +my $rel_dir = makeOutRel2Git($git_dir, $out_dir);
63 +
64 +# Print some information so the user feels informed
65 +print << "EOM";
66 +-----
67 +Generator: $gen
68 +Git dir: $git_dir
69 +Out dir: $out_dir
70 +-----
71 +Running GNU Make to figure out build structure...
72 +EOM
73 +
74 +# Pipe a make --dry-run into a variable, if not already loaded from file
75 +@makedry = `cd $git_dir && make -n MSVC=1 V=1 2>/dev/null` if !@makedry;
76 +
77 +# Parse the make output into usable info
78 +parseMakeOutput();
79 +
80 +# Finally, ask the generator to start generating..
81 +Generators::generate($gen, $git_dir, $out_dir, $rel_dir, %build_structure);
82 +
83 +# main flow ends here
84 +# -------------------------------------------------------------------------------------------------
85 +
86 +
87 +# 1) path: /foo/bar/baz 2) path: /foo/bar/baz 3) path: /foo/bar/baz
88 +# base: /foo/bar/baz/temp base: /foo/bar base: /tmp
89 +# rel: .. rel: baz rel: ../foo/bar/baz
90 +sub makeOutRel2Git
91 +{
92 + my ($path, $base) = @_;
93 + my $rel;
94 + if ("$path" eq "$base") {
95 + return ".";
96 + } elsif ($base =~ /^$path/) {
97 + # case 1
98 + my $tmp = $base;
99 + $tmp =~ s/^$path//;
100 + foreach (split('/', $tmp)) {
101 + $rel .= "../" if ("$_" ne "");
102 + }
103 + } elsif ($path =~ /^$base/) {
104 + # case 2
105 + $rel = $path;
106 + $rel =~ s/^$base//;
107 + $rel = "./$rel";
108 + } else {
109 + my $tmp = $base;
110 + foreach (split('/', $tmp)) {
111 + $rel .= "../" if ("$_" ne "");
112 + }
113 + $rel .= $path;
114 + }
115 + $rel =~ s/\/\//\//g; # simplify
116 + $rel =~ s/\/$//; # don't end with /
117 + return $rel;
118 +}
119 +
120 +sub parseMakeOutput
121 +{
122 + print "Parsing GNU Make output to figure out build structure...\n";
123 + my $line = 0;
124 + while (my $text = shift @makedry) {
125 + my $ate_next;
126 + do {
127 + $ate_next = 0;
128 + $line++;
129 + chomp $text;
130 + chop $text if ($text =~ /\r$/);
131 + if ($text =~ /\\$/) {
132 + $text =~ s/\\$//;
133 + $text .= shift @makedry;
134 + $ate_next = 1;
135 + }
136 + } while($ate_next);
137 +
138 + if($text =~ / -c /) {
139 + # compilation
140 + handleCompileLine($text, $line);
141 +
142 + } elsif ($text =~ / -o /) {
143 + # linking executable
144 + handleLinkLine($text, $line);
145 +
146 + } elsif ($text =~ /\.o / && $text =~ /\.a /) {
147 + # libifying
148 + handleLibLine($text, $line);
149 +#
150 +# } elsif ($text =~ /^cp /) {
151 +# # copy file around
152 +#
153 +# } elsif ($text =~ /^rm -f /) {
154 +# # shell command
155 +#
156 +# } elsif ($text =~ /^make[ \[]/) {
157 +# # make output
158 +#
159 +# } elsif ($text =~ /^echo /) {
160 +# # echo to file
161 +#
162 +# } elsif ($text =~ /^if /) {
163 +# # shell conditional
164 +#
165 +# } elsif ($text =~ /^tclsh /) {
166 +# # translation stuff
167 +#
168 +# } elsif ($text =~ /^umask /) {
169 +# # handling boilerplates
170 +#
171 +# } elsif ($text =~ /\$\(\:\)/) {
172 +# # ignore
173 +#
174 +# } elsif ($text =~ /^FLAGS=/) {
175 +# # flags check for dependencies
176 +#
177 +# } elsif ($text =~ /^'\/usr\/bin\/perl' -MError -e/) {
178 +# # perl commands for copying files
179 +#
180 +# } elsif ($text =~ /generate-cmdlist\.sh/) {
181 +# # command for generating list of commands
182 +#
183 +# } elsif ($text =~ /^test / && $text =~ /|| rm -f /) {
184 +# # commands removing executables, if they exist
185 +#
186 +# } elsif ($text =~ /new locations or Tcl/) {
187 +# # command for detecting Tcl/Tk changes
188 +#
189 +# } elsif ($text =~ /mkdir -p/) {
190 +# # command creating path
191 +#
192 +# } elsif ($text =~ /: no custom templates yet/) {
193 +# # whatever
194 +#
195 +# } else {
196 +# print "Unhandled (line: $line): $text\n";
197 + }
198 + }
199 +
200 +# use Data::Dumper;
201 +# print "Parsed build structure:\n";
202 +# print Dumper(%build_structure);
203 +}
204 +
205 +# variables for the compilation part of each step
206 +my (@defines, @incpaths, @cflags, @sources);
207 +
208 +sub clearCompileStep
209 +{
210 + @defines = ();
211 + @incpaths = ();
212 + @cflags = ();
213 + @sources = ();
214 +}
215 +
216 +sub removeDuplicates
217 +{
218 + my (%dupHash, $entry);
219 + %dupHash = map { $_, 1 } @defines;
220 + @defines = keys %dupHash;
221 +
222 + %dupHash = map { $_, 1 } @incpaths;
223 + @incpaths = keys %dupHash;
224 +
225 + %dupHash = map { $_, 1 } @cflags;
226 + @cflags = keys %dupHash;
227 +}
228 +
229 +sub handleCompileLine
230 +{
231 + my ($line, $lineno) = @_;
232 + my @parts = split(' ', $line);
233 + my $sourcefile;
234 + shift(@parts); # ignore cmd
235 + while (my $part = shift @parts) {
236 + if ("$part" eq "-o") {
237 + # ignore object file
238 + shift @parts;
239 + } elsif ("$part" eq "-c") {
240 + # ignore compile flag
241 + } elsif ("$part" eq "-c") {
242 + } elsif ($part =~ /^.?-I/) {
243 + push(@incpaths, $part);
244 + } elsif ($part =~ /^.?-D/) {
245 + push(@defines, $part);
246 + } elsif ($part =~ /^-/) {
247 + push(@cflags, $part);
248 + } elsif ($part =~ /\.(c|cc|cpp)$/) {
249 + $sourcefile = $part;
250 + } else {
251 + die "Unhandled compiler option @ line $lineno: $part";
252 + }
253 + }
254 + @{$compile_options{"${sourcefile}_CFLAGS"}} = @cflags;
255 + @{$compile_options{"${sourcefile}_DEFINES"}} = @defines;
256 + @{$compile_options{"${sourcefile}_INCPATHS"}} = @incpaths;
257 + clearCompileStep();
258 +}
259 +
260 +sub handleLibLine
261 +{
262 + my ($line, $lineno) = @_;
263 + my (@objfiles, @lflags, $libout, $part);
264 + # kill cmd and rm 'prefix'
265 + $line =~ s/^rm -f .* && .* rcs //;
266 + my @parts = split(' ', $line);
267 + while ($part = shift @parts) {
268 + if ($part =~ /^-/) {
269 + push(@lflags, $part);
270 + } elsif ($part =~ /\.(o|obj)$/) {
271 + push(@objfiles, $part);
272 + } elsif ($part =~ /\.(a|lib)$/) {
273 + $libout = $part;
274 + $libout =~ s/\.a$//;
275 + } else {
276 + die "Unhandled lib option @ line $lineno: $part";
277 + }
278 + }
279 +# print "LibOut: '$libout'\nLFlags: @lflags\nOfiles: @objfiles\n";
280 +# exit(1);
281 + foreach (@objfiles) {
282 + my $sourcefile = $_;
283 + $sourcefile =~ s/\.o/.c/;
284 + push(@sources, $sourcefile);
285 + push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}});
286 + push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}});
287 + push(@incpaths, @{$compile_options{"${sourcefile}_INCPATHS"}});
288 + }
289 + removeDuplicates();
290 +
291 + push(@{$build_structure{"LIBS"}}, $libout);
292 + @{$build_structure{"LIBS_${libout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_SOURCES",
293 + "_OBJECTS");
294 + @{$build_structure{"LIBS_${libout}_DEFINES"}} = @defines;
295 + @{$build_structure{"LIBS_${libout}_INCLUDES"}} = @incpaths;
296 + @{$build_structure{"LIBS_${libout}_CFLAGS"}} = @cflags;
297 + @{$build_structure{"LIBS_${libout}_LFLAGS"}} = @lflags;
298 + @{$build_structure{"LIBS_${libout}_SOURCES"}} = @sources;
299 + @{$build_structure{"LIBS_${libout}_OBJECTS"}} = @objfiles;
300 + clearCompileStep();
301 +}
302 +
303 +sub handleLinkLine
304 +{
305 + my ($line, $lineno) = @_;
306 + my (@objfiles, @lflags, @libs, $appout, $part);
307 + my @parts = split(' ', $line);
308 + shift(@parts); # ignore cmd
309 + while ($part = shift @parts) {
310 + if ($part =~ /^-IGNORE/) {
311 + push(@lflags, $part);
312 + } elsif ($part =~ /^-[GRIMDO]/) {
313 + # eat compiler flags
314 + } elsif ("$part" eq "-o") {
315 + $appout = shift @parts;
316 + } elsif ("$part" eq "-lz") {
317 + push(@libs, "zlib.lib");
318 + } elsif ($part =~ /^-/) {
319 + push(@lflags, $part);
320 + } elsif ($part =~ /\.(a|lib)$/) {
321 + $part =~ s/\.a$/.lib/;
322 + push(@libs, $part);
323 + } elsif ($part =~ /\.(o|obj)$/) {
324 + push(@objfiles, $part);
325 + } else {
326 + die "Unhandled lib option @ line $lineno: $part";
327 + }
328 + }
329 +# print "AppOut: '$appout'\nLFlags: @lflags\nLibs : @libs\nOfiles: @objfiles\n";
330 +# exit(1);
331 + foreach (@objfiles) {
332 + my $sourcefile = $_;
333 + $sourcefile =~ s/\.o/.c/;
334 + push(@sources, $sourcefile);
335 + push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}});
336 + push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}});
337 + push(@incpaths, @{$compile_options{"${sourcefile}_INCPATHS"}});
338 + }
339 + removeDuplicates();
340 +
341 + removeDuplicates();
342 + push(@{$build_structure{"APPS"}}, $appout);
343 + @{$build_structure{"APPS_${appout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_LFLAGS",
344 + "_SOURCES", "_OBJECTS", "_LIBS");
345 + @{$build_structure{"APPS_${appout}_DEFINES"}} = @defines;
346 + @{$build_structure{"APPS_${appout}_INCLUDES"}} = @incpaths;
347 + @{$build_structure{"APPS_${appout}_CFLAGS"}} = @cflags;
348 + @{$build_structure{"APPS_${appout}_LFLAGS"}} = @lflags;
349 + @{$build_structure{"APPS_${appout}_SOURCES"}} = @sources;
350 + @{$build_structure{"APPS_${appout}_OBJECTS"}} = @objfiles;
351 + @{$build_structure{"APPS_${appout}_LIBS"}} = @libs;
352 + clearCompileStep();
353 +}
contrib/buildsystems/generate new
+29
@@ -0,0 +1,29 @@
1 +#!/usr/bin/perl -w
2 +######################################################################
3 +# Generate buildsystem files
4 +#
5 +# This script generate buildsystem files based on the output of a
6 +# GNU Make --dry-run, enabling Windows users to develop Git with their
7 +# trusted IDE with native projects.
8 +#
9 +# Note:
10 +# It is not meant as *the* way of building Git with MSVC, but merely a
11 +# convenience. The correct way of building Git with MSVC is to use the
12 +# GNU Make tool to build with the maintained Makefile in the root of
13 +# the project. If you have the msysgit environment installed and
14 +# available in your current console, together with the Visual Studio
15 +# environment you wish to build for, all you have to do is run the
16 +# command:
17 +# make MSVC=1
18 +#
19 +# Copyright (C) 2009 Marius Storm-Olsen <mstormo@gmail.com>
20 +######################################################################
21 +use strict;
22 +use File::Basename;
23 +use Cwd;
24 +
25 +my $git_dir = getcwd();
26 +$git_dir =~ s=\\=/=g;
27 +$git_dir = dirname($git_dir) while (!-e "$git_dir/git.c" && "$git_dir" ne "");
28 +die "Couldn't find Git repo" if ("$git_dir" eq "");
29 +exec join(" ", ("PERL5LIB=${git_dir}/contrib/buildsystems ${git_dir}/contrib/buildsystems/engine.pl", @ARGV));
contrib/buildsystems/parse.pl new
+228
@@ -0,0 +1,228 @@
1 +#!/usr/bin/perl -w
2 +######################################################################
3 +# Do not call this script directly!
4 +#
5 +# The generate script ensures that @INC is correct before the engine
6 +# is executed.
7 +#
8 +# Copyright (C) 2009 Marius Storm-Olsen <mstormo@gmail.com>
9 +######################################################################
10 +use strict;
11 +use File::Basename;
12 +use Cwd;
13 +
14 +my $file = $ARGV[0];
15 +die "No file provided!" if !defined $file;
16 +
17 +my ($cflags, $target, $type, $line);
18 +
19 +open(F, "<$file") || die "Couldn't open file $file";
20 +my @data = <F>;
21 +close(F);
22 +
23 +while (my $text = shift @data) {
24 + my $ate_next;
25 + do {
26 + $ate_next = 0;
27 + $line++;
28 + chomp $text;
29 + chop $text if ($text =~ /\r$/);
30 + if ($text =~ /\\$/) {
31 + $text =~ s/\\$//;
32 + $text .= shift @data;
33 + $ate_next = 1;
34 + }
35 + } while($ate_next);
36 +
37 + if($text =~ / -c /) {
38 + # compilation
39 + handleCompileLine($text, $line);
40 +
41 + } elsif ($text =~ / -o /) {
42 + # linking executable
43 + handleLinkLine($text, $line);
44 +
45 + } elsif ($text =~ /\.o / && $text =~ /\.a /) {
46 + # libifying
47 + handleLibLine($text, $line);
48 +
49 +# } elsif ($text =~ /^cp /) {
50 +# # copy file around
51 +#
52 +# } elsif ($text =~ /^rm -f /) {
53 +# # shell command
54 +#
55 +# } elsif ($text =~ /^make[ \[]/) {
56 +# # make output
57 +#
58 +# } elsif ($text =~ /^echo /) {
59 +# # echo to file
60 +#
61 +# } elsif ($text =~ /^if /) {
62 +# # shell conditional
63 +#
64 +# } elsif ($text =~ /^tclsh /) {
65 +# # translation stuff
66 +#
67 +# } elsif ($text =~ /^umask /) {
68 +# # handling boilerplates
69 +#
70 +# } elsif ($text =~ /\$\(\:\)/) {
71 +# # ignore
72 +#
73 +# } elsif ($text =~ /^FLAGS=/) {
74 +# # flags check for dependencies
75 +#
76 +# } elsif ($text =~ /^'\/usr\/bin\/perl' -MError -e/) {
77 +# # perl commands for copying files
78 +#
79 +# } elsif ($text =~ /generate-cmdlist\.sh/) {
80 +# # command for generating list of commands
81 +#
82 +# } elsif ($text =~ /^test / && $text =~ /|| rm -f /) {
83 +# # commands removing executables, if they exist
84 +#
85 +# } elsif ($text =~ /new locations or Tcl/) {
86 +# # command for detecting Tcl/Tk changes
87 +#
88 +# } elsif ($text =~ /mkdir -p/) {
89 +# # command creating path
90 +#
91 +# } elsif ($text =~ /: no custom templates yet/) {
92 +# # whatever
93 +
94 + } else {
95 +# print "Unhandled (line: $line): $text\n";
96 + }
97 +}
98 +close(F);
99 +
100 +# use Data::Dumper;
101 +# print "Parsed build structure:\n";
102 +# print Dumper(%build_structure);
103 +
104 +# -------------------------------------------------------------------
105 +# Functions under here
106 +# -------------------------------------------------------------------
107 +my (%build_structure, @defines, @incpaths, @cflags, @sources);
108 +
109 +sub clearCompileStep
110 +{
111 + @defines = ();
112 + @incpaths = ();
113 + @cflags = ();
114 + @sources = ();
115 +}
116 +
117 +sub removeDuplicates
118 +{
119 + my (%dupHash, $entry);
120 + %dupHash = map { $_, 1 } @defines;
121 + @defines = keys %dupHash;
122 +
123 + %dupHash = map { $_, 1 } @incpaths;
124 + @incpaths = keys %dupHash;
125 +
126 + %dupHash = map { $_, 1 } @cflags;
127 + @cflags = keys %dupHash;
128 +
129 + %dupHash = map { $_, 1 } @sources;
130 + @sources = keys %dupHash;
131 +}
132 +
133 +sub handleCompileLine
134 +{
135 + my ($line, $lineno) = @_;
136 + my @parts = split(' ', $line);
137 + shift(@parts); # ignore cmd
138 + while (my $part = shift @parts) {
139 + if ("$part" eq "-o") {
140 + # ignore object file
141 + shift @parts;
142 + } elsif ("$part" eq "-c") {
143 + # ignore compile flag
144 + } elsif ("$part" eq "-c") {
145 + } elsif ($part =~ /^.?-I/) {
146 + push(@incpaths, $part);
147 + } elsif ($part =~ /^.?-D/) {
148 + push(@defines, $part);
149 + } elsif ($part =~ /^-/) {
150 + push(@cflags, $part);
151 + } elsif ($part =~ /\.(c|cc|cpp)$/) {
152 + push(@sources, $part);
153 + } else {
154 + die "Unhandled compiler option @ line $lineno: $part";
155 + }
156 + }
157 + #print "Sources: @sources\nCFlags: @cflags\nDefine: @defines\nIncpat: @incpaths\n";
158 + #exit(1);
159 +}
160 +
161 +sub handleLibLine
162 +{
163 + my ($line, $lineno) = @_;
164 + my (@objfiles, @lflags, $libout, $part);
165 + # kill cmd and rm 'prefix'
166 + $line =~ s/^rm -f .* && .* rcs //;
167 + my @parts = split(' ', $line);
168 + while ($part = shift @parts) {
169 + if ($part =~ /^-/) {
170 + push(@lflags, $part);
171 + } elsif ($part =~ /\.(o|obj)$/) {
172 + push(@objfiles, $part);
173 + } elsif ($part =~ /\.(a|lib)$/) {
174 + $libout = $part;
175 + } else {
176 + die "Unhandled lib option @ line $lineno: $part";
177 + }
178 + }
179 + #print "LibOut: '$libout'\nLFlags: @lflags\nOfiles: @objfiles\n";
180 + #exit(1);
181 + removeDuplicates();
182 + push(@{$build_structure{"LIBS"}}, $libout);
183 + @{$build_structure{"LIBS_${libout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_SOURCES",
184 + "_OBJECTS");
185 + @{$build_structure{"LIBS_${libout}_DEFINES"}} = @defines;
186 + @{$build_structure{"LIBS_${libout}_INCLUDES"}} = @incpaths;
187 + @{$build_structure{"LIBS_${libout}_CFLAGS"}} = @cflags;
188 + @{$build_structure{"LIBS_${libout}_SOURCES"}} = @sources;
189 + @{$build_structure{"LIBS_${libout}_OBJECTS"}} = @objfiles;
190 + clearCompileStep();
191 +}
192 +
193 +sub handleLinkLine
194 +{
195 + my ($line, $lineno) = @_;
196 + my (@objfiles, @lflags, @libs, $appout, $part);
197 + my @parts = split(' ', $line);
198 + shift(@parts); # ignore cmd
199 + while ($part = shift @parts) {
200 + if ($part =~ /^-[GRIDO]/) {
201 + # eat compiler flags
202 + } elsif ("$part" eq "-o") {
203 + $appout = shift @parts;
204 + } elsif ($part =~ /^-/) {
205 + push(@lflags, $part);
206 + } elsif ($part =~ /\.(a|lib)$/) {
207 + push(@libs, $part);
208 + } elsif ($part =~ /\.(o|obj)$/) {
209 + push(@objfiles, $part);
210 + } else {
211 + die "Unhandled lib option @ line $lineno: $part";
212 + }
213 + }
214 + #print "AppOut: '$appout'\nLFlags: @lflags\nLibs : @libs\nOfiles: @objfiles\n";
215 + #exit(1);
216 + removeDuplicates();
217 + push(@{$build_structure{"APPS"}}, $appout);
218 + @{$build_structure{"APPS_${appout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_LFLAGS",
219 + "_SOURCES", "_OBJECTS", "_LIBS");
220 + @{$build_structure{"APPS_${appout}_DEFINES"}} = @defines;
221 + @{$build_structure{"APPS_${appout}_INCLUDES"}} = @incpaths;
222 + @{$build_structure{"APPS_${appout}_CFLAGS"}} = @cflags;
223 + @{$build_structure{"APPS_${appout}_LFLAGS"}} = @lflags;
224 + @{$build_structure{"APPS_${appout}_SOURCES"}} = @sources;
225 + @{$build_structure{"APPS_${appout}_OBJECTS"}} = @objfiles;
226 + @{$build_structure{"APPS_${appout}_LIBS"}} = @libs;
227 + clearCompileStep();
228 +}