Skip to content

Commit bfe3521

Browse files
Martin Valgurdanimtb
Martin Valgur
andauthored
(#18873) cc65: migrate to Conan v2
* cc65: migrate to Conan v2 * cc65: add VirtualBuildEnv * cc65: fix issue on Windows * cc65: cross-compiling is limited to native architectures only * cc65: drop test_v1_package It refuses to work despite package_info() and test_v1_package being virtually unchanged. * cc65: fix MSVC build * cc65: workaround for an MSVC build issue * Update recipes/cc65/all/conanfile.py * Update recipes/cc65/all/conanfile.py --------- Co-authored-by: Daniel <[email protected]>
1 parent 6a852f7 commit bfe3521

File tree

3 files changed

+138
-149
lines changed

3 files changed

+138
-149
lines changed

recipes/cc65/all/conandata.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ sources:
88
patches:
99
"2.18":
1010
- patch_file: "patches/2.18-0001-no-embedded-paths-makefile.patch"
11-
base_path: "source_subfolder"
1211
- patch_file: "patches/2.18-0002-libsrc-use-extension.patch"
13-
base_path: "source_subfolder"
1412
"2.19":
1513
- patch_file: "patches/2.19-0001-no-embedded-paths-makefile.patch"
16-
base_path: "source_subfolder"
1714
- patch_file: "patches/2.19-0002-libsrc-use-extension.patch"
18-
base_path: "source_subfolder"

recipes/cc65/all/conanfile.py

Lines changed: 114 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,150 @@
1-
from conans import AutoToolsBuildEnvironment, ConanFile, MSBuild, tools
2-
from conans.errors import ConanInvalidConfiguration
31
import os
42

3+
from conan import ConanFile
4+
from conan.errors import ConanInvalidConfiguration
5+
from conan.tools.build import can_run
6+
from conan.tools.files import apply_conandata_patches, chdir, copy, export_conandata_patches, get, replace_in_file, rmdir
7+
from conan.tools.gnu import Autotools, AutotoolsToolchain
8+
from conan.tools.layout import basic_layout
9+
from conan.tools.microsoft import MSBuild, is_msvc, msvs_toolset, MSBuildToolchain
10+
11+
required_conan_version = ">=1.53.0"
12+
513

614
class Cc65Conan(ConanFile):
715
name = "cc65"
8-
url = "https://github.com/conan-io/conan-center-index"
9-
homepage = "https://cc65.github.io/"
1016
description = "A freeware C compiler for 6502 based systems"
1117
license = "Zlib"
12-
topics = ("conan", "cc65", "compiler", "cmos", "6502", "8bit")
13-
exports_sources = "patches/**"
18+
url = "https://github.com/conan-io/conan-center-index"
19+
homepage = "https://cc65.github.io/"
20+
topics = ("compiler", "cmos", "6502", "8bit")
1421

22+
package_type = "application"
1523
settings = "os", "arch", "compiler", "build_type"
1624

17-
_autotools = None
18-
_source_subfolder = "source_subfolder"
25+
def export_sources(self):
26+
export_conandata_patches(self)
1927

2028
def configure(self):
21-
del self.settings.compiler.libcxx
22-
del self.settings.compiler.cppstd
23-
if self.settings.compiler == "Visual Studio":
24-
if self.settings.arch not in ("x86", "x86_64"):
25-
raise ConanInvalidConfiguration("Invalid arch")
29+
self.settings.rm_safe("compiler.libcxx")
30+
self.settings.rm_safe("compiler.cppstd")
31+
32+
def layout(self):
33+
basic_layout(self, src_folder="src")
34+
35+
def package_id(self):
36+
if is_msvc(self.info):
37+
if self.info.settings.arch == "x86_64":
38+
self.info.settings.arch = "x86"
39+
del self.info.settings.compiler
40+
41+
def validate(self):
42+
if not can_run(self):
43+
raise ConanInvalidConfiguration(
44+
f"Compiling for {self.settings.arch} is not supported. "
45+
"cc65 needs to be able to run the built executables during the build process"
46+
)
47+
if is_msvc(self):
48+
if self.settings.arch not in ["x86", "x86_64"]:
49+
raise ConanInvalidConfiguration(f"{self.settings.arch} is not supported on MSVC")
2650
if self.settings.arch == "x86_64":
2751
self.output.info("This recipe will build x86 instead of x86_64 (the binaries are compatible)")
2852

2953
def build_requirements(self):
30-
if self.settings.compiler == "Visual Studio" and not tools.which("make"):
31-
self.build_requires("make/4.2.1")
54+
if is_msvc(self):
55+
self.tool_requires("make/4.4")
3256

3357
def source(self):
34-
tools.get(**self.conan_data["sources"][self.version])
35-
extracted_dir = self.name + "-" + self.version
36-
os.rename(extracted_dir, self._source_subfolder)
37-
38-
@property
39-
def _datadir(self):
40-
return os.path.join(self.package_folder, "bin", "share", "cc65")
41-
42-
@property
43-
def _samplesdir(self):
44-
return os.path.join(self.package_folder, "samples")
45-
46-
def _build_msvc(self):
47-
msbuild = MSBuild(self)
48-
msvc_platforms = {
49-
"x86": "Win32",
50-
}
51-
arch = str(self.settings.arch)
52-
if arch != "x86":
53-
self.output.warn("{} detected: building x86 instead".format(self.settings.arch))
54-
arch = "x86"
55-
56-
msbuild.build(os.path.join(self._source_subfolder, "src", "cc65.sln"),
57-
build_type="Debug" if self.settings.build_type == "Debug" else "Release",
58-
arch=arch, platforms=msvc_platforms)
59-
autotools = self._configure_autotools()
60-
with tools.chdir(os.path.join(self._source_subfolder, "libsrc")):
61-
autotools.make()
62-
63-
def _configure_autotools(self):
64-
if self._autotools:
65-
return self._autotools
66-
self._autotools = AutoToolsBuildEnvironment(self)
67-
return self._autotools
68-
69-
@property
70-
def _make_args(self):
71-
datadir = self._datadir
72-
prefix = self.package_folder
73-
samplesdir = self._samplesdir
74-
if tools.os_info.is_windows:
75-
datadir = tools.unix_path(datadir)
76-
prefix = tools.unix_path(prefix)
77-
samplesdir = tools.unix_path(samplesdir)
78-
args = [
79-
"PREFIX={}".format(prefix),
80-
"datadir={}".format(datadir),
81-
"samplesdir={}".format(samplesdir),
58+
get(self, **self.conan_data["sources"][self.version], strip_root=True)
59+
60+
def generate(self):
61+
if is_msvc(self):
62+
tc = MSBuildToolchain(self)
63+
tc.generate()
64+
tc = AutotoolsToolchain(self)
65+
tc.make_args += [
66+
"PREFIX=/",
67+
"datadir=/bin/share/cc65",
68+
"samplesdir=/samples",
8269
]
8370
if self.settings.os == "Windows":
84-
args.append("EXE_SUFFIX=.exe")
85-
return args
86-
87-
def _build_autotools(self):
88-
autotools = self._configure_autotools()
89-
with tools.chdir(os.path.join(self._source_subfolder)):
90-
autotools.make(args=self._make_args)
71+
tc.make_args.append("EXE_SUFFIX=.exe")
72+
tc.generate()
9173

9274
def _patch_sources(self):
93-
for patch in self.conan_data["patches"][self.version]:
94-
tools.patch(**patch)
95-
if self.settings.compiler == "Visual Studio":
96-
with tools.chdir(os.path.join(self._source_subfolder, "src")):
97-
for fn in os.listdir("."):
98-
if not fn.endswith(".vcxproj"):
99-
continue
100-
tools.replace_in_file(fn, "v141", tools.msvs_toolset(self))
101-
tools.replace_in_file(fn, "<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>", "")
75+
apply_conandata_patches(self)
76+
if is_msvc(self):
77+
for vcxproj in self.source_path.joinpath("src").rglob("*.vcxproj"):
78+
replace_in_file(self, vcxproj, "v141", msvs_toolset(self))
79+
replace_in_file(self, vcxproj, "<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>", "")
10280
if self.settings.os == "Windows":
10381
# Add ".exe" suffix to calls from cl65 to other utilities
104-
for fn, var in (("cc65", "CC65"), ("ca65", "CA65"), ("co65", "CO65"), ("ld65", "LD65"), ("grc65", "GRC")):
105-
v = "{},".format(var).ljust(5)
106-
tools.replace_in_file(os.path.join(self._source_subfolder, "src", "cl65", "main.c"),
107-
"CmdInit (&{v} CmdPath, \"{n}\");".format(v=v, n=fn),
108-
"CmdInit (&{v} CmdPath, \"{n}.exe\");".format(v=v, n=fn))
82+
for fn, var in [
83+
("cc65", "CC65"),
84+
("ca65", "CA65"),
85+
("co65", "CO65"),
86+
("ld65", "LD65"),
87+
("grc65", "GRC"),
88+
]:
89+
v = f"{var},".ljust(5)
90+
replace_in_file(self, os.path.join(self.source_folder, "src", "cl65", "main.c"),
91+
f'CmdInit (&{v} CmdPath, "{fn}");',
92+
f'CmdInit (&{v} CmdPath, "{fn}.exe");')
93+
# Fix mkdir failing on Windows due to -p being unavailable there
94+
# https://github.com/conan-io/conan-center-index/pull/18873#issuecomment-1841989876
95+
replace_in_file(self, os.path.join(self.source_folder, "libsrc", "Makefile"),
96+
r'MKDIR = mkdir $(subst /,\,$1)',
97+
r'MKDIR = if not exist "$(subst /,\,$1)" mkdir "$(subst /,\,$1)"')
10998

11099
def build(self):
111100
self._patch_sources()
112-
if self.settings.compiler == "Visual Studio":
113-
self._build_msvc()
101+
if is_msvc(self):
102+
msbuild = MSBuild(self)
103+
msbuild.platform = "Win32"
104+
msbuild.build_type = "Debug" if self.settings.build_type == "Debug" else "Release"
105+
msbuild.build(sln=os.path.join(self.source_folder, "src", "cc65.sln"))
106+
with chdir(self, os.path.join(self.source_folder, "libsrc")):
107+
autotools = Autotools(self)
108+
autotools.make()
114109
else:
115-
self._build_autotools()
116-
117-
def _package_msvc(self):
118-
self.copy("*.exe", src=os.path.join(self._source_subfolder, "bin"), dst=os.path.join(self.package_folder, "bin"), keep_path=False)
119-
for dir in ("asminc", "cfg", "include", "lib", "target"):
120-
self.copy("*", src=os.path.join(self._source_subfolder, dir), dst=os.path.join(self._datadir, dir))
121-
122-
def _package_autotools(self):
123-
autotools = self._configure_autotools()
124-
with tools.chdir(os.path.join(self.build_folder, self._source_subfolder)):
125-
autotools.install(args=self._make_args)
126-
127-
tools.rmdir(self._samplesdir)
128-
tools.rmdir(os.path.join(self.package_folder, "share"))
110+
with chdir(self, self.source_folder):
111+
autotools = Autotools(self)
112+
autotools.make()
129113

130114
def package(self):
131-
self.copy(pattern="LICENSE", dst="licenses", src=self._source_subfolder)
132-
if self.settings.compiler == "Visual Studio":
133-
self._package_msvc()
115+
copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses"))
116+
if is_msvc(self):
117+
copy(self, "*.exe",
118+
dst=os.path.join(self.package_folder, "bin"),
119+
src=os.path.join(self.source_folder, "bin"),
120+
keep_path=False)
121+
for folder in ("asminc", "cfg", "include", "lib", "target"):
122+
copy(self, "*",
123+
dst=os.path.join(self.package_folder, "bin", "share", "cc65", folder),
124+
src=os.path.join(self.source_folder, folder))
134125
else:
135-
self._package_autotools()
136-
137-
def package_id(self):
138-
del self.info.settings.compiler
139-
if self.settings.compiler == "Visual Studio":
140-
if self.settings.arch == "x86_64":
141-
self.info.settings.arch = "x86"
126+
with chdir(self, os.path.join(self.source_folder)):
127+
autotools = Autotools(self)
128+
autotools.install()
129+
rmdir(self, os.path.join(self.package_path, "samples"))
130+
rmdir(self, os.path.join(self.package_folder, "share"))
142131

143132
def package_info(self):
144-
bindir = os.path.join(self.package_folder, "bin")
145-
self.output.info("Appending PATH environment variable: %s" % bindir)
146-
self.env_info.PATH.append(bindir)
147-
148-
self.output.info("Seting CC65_HOME environment variable: %s" % self._datadir)
149-
self.env_info.CC65_HOME = self._datadir
133+
self.cpp_info.frameworkdirs = []
134+
self.cpp_info.libdirs = []
135+
self.cpp_info.resdirs = []
136+
self.cpp_info.includedirs = []
150137

151138
bin_ext = ".exe" if self.settings.os == "Windows" else ""
139+
bindir = os.path.join(self.package_folder, "bin")
140+
self.buildenv_info.define_path("CC65_HOME", os.path.join(self.package_folder, "bin", "share", "cc65"))
141+
self.buildenv_info.define_path("CC65", os.path.join(bindir, "cc65" + bin_ext))
142+
self.buildenv_info.define_path("AS65", os.path.join(bindir, "ca65" + bin_ext))
143+
self.buildenv_info.define_path("LD65", os.path.join(bindir, "cl65" + bin_ext))
152144

153-
cc65_cc = os.path.join(bindir, "cc65" + bin_ext)
154-
self.output.info("Seting CC65 environment variable: {}".format(cc65_cc))
155-
self.env_info.CC65 = cc65_cc
156-
157-
cc65_as = os.path.join(bindir, "ca65" + bin_ext)
158-
self.output.info("Seting AS65 environment variable: {}".format(cc65_as))
159-
self.env_info.AS65 = cc65_as
160-
161-
cc65_ld = os.path.join(bindir, "cl65" + bin_ext)
162-
self.output.info("Seting LD65 environment variable: {}".format(cc65_ld))
163-
self.env_info.LD65 = cc65_ld
145+
# TODO: Legacy, to be removed on Conan 2.0
146+
self.env_info.PATH.append(bindir)
147+
self.env_info.CC65_HOME = os.path.join(self.package_folder, "bin", "share", "cc65")
148+
self.env_info.CC65 = os.path.join(bindir, "cc65" + bin_ext)
149+
self.env_info.AS65 = os.path.join(bindir, "ca65" + bin_ext)
150+
self.env_info.LD65 = os.path.join(bindir, "cl65" + bin_ext)
Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,39 @@
1-
from conans import ConanFile, tools
21
import os
32
import shutil
43

4+
from conan import ConanFile
5+
from conan.tools.build import can_run
6+
from conan.tools.files import mkdir, rm
7+
from conan.tools.layout import basic_layout
8+
59

610
class TestPackageConan(ConanFile):
711
settings = "os", "arch", "compiler", "build_type"
8-
9-
exports_sources = "hello.c", "text.s"
12+
generators = "VirtualRunEnv", "VirtualBuildEnv"
13+
test_type = "explicit"
1014

1115
_targets = ("c64", "apple2")
1216

17+
def build_requirements(self):
18+
self.tool_requires(self.tested_reference_str)
19+
20+
def layout(self):
21+
basic_layout(self)
22+
1323
def build(self):
14-
if not tools.cross_building(self.settings):
15-
for src in self.exports_sources:
24+
if can_run(self):
25+
for src in ["hello.c", "text.s"]:
1626
shutil.copy(os.path.join(self.source_folder, src), os.path.join(self.build_folder, src))
1727
for target in self._targets:
18-
output = "hello_{}".format(target)
19-
tools.mkdir(target)
20-
try:
21-
# Try removing the output file to give confidence it is created by cc65
22-
os.unlink(output)
23-
except FileNotFoundError:
24-
pass
25-
self.run("{p} -O -t {t} hello.c -o {t}/hello.s".format(p=os.environ["CC65"], t=target))
26-
self.run("{p} -t {t} {t}/hello.s -o {t}/hello.o".format(p=os.environ["AS65"], t=target))
27-
self.run("{p} -t {t} text.s -o {t}/text.o".format(p=os.environ["AS65"], t=target))
28-
self.run("{p} -o {o} -t {t} {t}/hello.o {t}/text.o {t}.lib".format(o=output, p=os.environ["LD65"], t=target))
28+
output = f"hello_{target}"
29+
mkdir(self, target)
30+
rm(self, output, self.build_folder)
31+
self.run(f"cc65 -O -t {target} hello.c -o {target}/hello.s")
32+
self.run(f"ca65 -t {target} {target}/hello.s -o {target}/hello.o")
33+
self.run(f"ca65 -t {target} text.s -o {target}/text.o")
34+
self.run(f"ld65 -o {output} -t {target} {target}/hello.o {target}/text.o {target}.lib")
2935

3036
def test(self):
31-
if not tools.cross_building(self.settings):
37+
if can_run(self):
3238
for target in self._targets:
33-
assert os.path.isfile("hello_{}".format(target))
39+
assert os.path.isfile(f"hello_{target}")

0 commit comments

Comments
 (0)