Skip to content

Commit

Permalink
Added MAKEPROJECTS support
Browse files Browse the repository at this point in the history
If a build_rules.py file has MAKEPROJECTS variable, it can list all the projects that will be generated by default if "makeprojects" is run without any parameters
  • Loading branch information
burgerbecky committed Aug 19, 2024
1 parent 5700178 commit 8393037
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 101 deletions.
293 changes: 262 additions & 31 deletions makeprojects/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
import os
import argparse

from burger import convert_to_array

from .core import Solution, Project, Configuration
from .config import BUILD_RULES_PY
from .__init__ import __version__
from .defaults import get_project_name, get_platform, get_ide, \
get_project_type, get_configuration_list
from .util import get_build_rules, load_build_rules
from .util import get_build_rules, load_build_rules, do_generate_build_rules

########################################

Expand Down Expand Up @@ -198,30 +200,30 @@ def create_parser():
########################################


def get_project_list(args, build_rules_list, working_directory):
def get_project_list(parsed, build_rules_list, working_directory):
"""
From the command line or the build rules, determine the project target list.
"""

# Start with determining the project name
project_name = get_project_name(
build_rules_list, working_directory, args.verbose, args.name)
build_rules_list, working_directory, parsed.verbose, parsed.name)

# Determine the project type
project_type = get_project_type(
build_rules_list, args.verbose, args.project_type)
build_rules_list, parsed.verbose, parsed.project_type)

# Determine the list of platforms to generate projects for.
platform = get_platform(
build_rules_list, args.verbose, args.platform)
build_rules_list, parsed.verbose, parsed.platform)

# Determine the list of IDEs to generate projects for.
ide = get_ide(build_rules_list, args.verbose, args.ide, platform)
ide = get_ide(build_rules_list, parsed.verbose, parsed.ide, platform)

# Start with the solution
solution = Solution(
name=project_name,
verbose=args.verbose,
verbose=parsed.verbose,
working_directory=working_directory,
ide=ide)

Expand All @@ -238,7 +240,7 @@ def get_project_list(args, build_rules_list, working_directory):
for platform_item in platform.get_expanded():
# Create the configurations for this platform
for config_item in get_configuration_list(
build_rules_list, args.configurations,
build_rules_list, parsed.configurations,
platform_item, ide):

# Set the platform
Expand Down Expand Up @@ -285,29 +287,258 @@ def get_project_list(args, build_rules_list, working_directory):
########################################


def process(working_directory, args):
def process(working_directory, parsed):
"""
Process a solution.
Args:
working_directory: Directory to process.
args: Args for determining verbosity for output
parsed: Args for determining verbosity for output
Returns:
Zero on no error, non zero integer on error
"""

if args.verbose:
if parsed.verbose:
print("Making \"{}\".".format(working_directory))

# Are there build rules in this directory?
build_rules_list = get_build_rules(
working_directory, args.verbose, args.rules_file, "MAKEPROJECTS")
working_directory, parsed.verbose, parsed.rules_file, "MAKEPROJECTS")

if not build_rules_list:
print("Fatal error, no " + BUILD_RULES_PY + " exist anywhere.")
return 10

return get_project_list(args, build_rules_list, working_directory)
return get_project_list(parsed, build_rules_list, working_directory)

########################################


def process_project_configurations(
parsed, working_directory, entry, args):
"""
Generate project file with configurations
Given a dict with keys to generate a project, create all the
project files for all requested IDEs
Assume -n, -p, -t and -g are preset
Args:
parsed: An ArgumentParser object with attribute generate_build_rules
working_directory: Directory to store the build_rules.py
entry: Dictionary of keys to use to create the project files
args: Arguments so far
Returns:
Integer error code
"""

# Are there configurations?
configurations = entry.get("configuration")
new_args = []

# Is verbose mode enabled?
if parsed.verbose:
new_args.append("-v")

# Any configuration to add?
if configurations:

# Make sure it's an array
configurations = convert_to_array(configurations)
for configuration in configurations:
new_args.append("-c")
new_args.append(configuration)

# Generate the project file
return main(working_directory, args + new_args)

########################################


def process_project_types(
parsed, working_directory, entry, args):
"""
Process a dict entry with the -n, -p, -g parameters already set
Given a dict with keys to generate a project, create all the
project files for all requested IDEs
Args:
parsed: An ArgumentParser object with attribute generate_build_rules
working_directory: Directory to store the build_rules.py
entry: Dictionary of keys to use to create the project files
args: Arguments so far
Returns:
Integer error code
"""

# Is there an ide?
types = entry.get("type")
if not types:
return process_project_configurations(
parsed, working_directory, entry, args)

# Make sure it's an array
types = convert_to_array(types)
error = 0
for item in types:
new_args = ["-t", item]
error = process_project_configurations(
parsed, working_directory, entry, args + new_args)
if error:
return error

return error

########################################


def process_project_ides(
parsed, working_directory, entry, args):
"""
Process a dict entry with the -n and -p parameters already set
Given a dict with keys to generate a project, create all the
project files for all requested IDEs
Args:
parsed: An ArgumentParser object with attribute generate_build_rules
working_directory: Directory to store the build_rules.py
entry: Dictionary of keys to use to create the project files
args: Arguments so far
Returns:
Integer error code
"""

# Is there an ide?
ide = entry.get("ide")
if not ide:
return process_project_types(parsed, working_directory, entry, args)

# Make sure it's an array
ide = convert_to_array(ide)
error = 0
for item in ide:
new_args = ["-g", item]
error = process_project_types(
parsed, working_directory, entry, args + new_args)
if error:
return error

return error

########################################


def process_project_platforms(
parsed, working_directory, entry, args):
"""
Process a dict entry with the -n parameter already set
Given a dict with keys to generate a project, create all the
project files for all requested IDEs
Args:
parsed: An ArgumentParser object with attribute generate_build_rules
working_directory: Directory to store the build_rules.py
entry: Dictionary of keys to use to create the project files
args: Arguments so far
Returns:
Integer error code
"""

# Is there a platform?
platform = entry.get("platform")
if not platform:
return process_project_ides(parsed, working_directory, entry, args)

# Make sure it's an array
platform = convert_to_array(platform)
error = 0
for item in platform:
new_args = ["-p", item]
error = process_project_ides(
parsed, working_directory, entry, args + new_args)
if error:
return error

return error

########################################


def process_proj_names(parsed, working_directory, entry):
"""
Process a dict entry to generate project files
Given a dict with keys to generate a project, create all the
project files for all requested IDEs
Args:
parsed: An ArgumentParser object with attribute generate_build_rules
working_directory: Directory to store the build_rules.py
entry: Dictionary of keys to use to create the project files
Returns:
Integer error code
"""

# Is there a name?
name = entry.get("name")
if not name:
return process_project_platforms(parsed, working_directory, entry, [])

# Make sure it's an array
name = convert_to_array(name)
error = 0
for item in name:
args = ["-n", item]
error = process_project_platforms(
parsed, working_directory, entry, args)
if error:
return error

return error

########################################


def process_makeprojects(parsed, working_directory):
"""
Process using default behavior from MAKEPROJECTS
Check if there is a build_rules.py in the current directory
and if so, if there's a MAKEPROJECTS value, use it to process
all the project files.
Args:
parsed: An ArgumentParser object with attribute generate_build_rules
working_directory: Directory to store the build_rules.py
Returns:
None or an integer error code
"""

# Get the path to the requested rules
library_rules = os.path.join(working_directory, BUILD_RULES_PY)

# Load in build_rules.py
build_rules = load_build_rules(library_rules)

# Not found? Abort
if not build_rules:
return None

# Does the file have the attribute?
make_proj = getattr(build_rules, "MAKEPROJECTS", None)
if not make_proj:
return None

# Iterate over every MAKEPROJECTS entry
for entry in make_proj:
error = process_proj_names(parsed, working_directory, entry)
if error:
break
return error

########################################

Expand Down Expand Up @@ -338,31 +569,31 @@ def main(working_directory=None, args=None):
parser = create_parser()

# Parse everything
args = parser.parse_args(args=args)

# Output default configuration
if args.generate_build_rules:
# pylint: disable=import-outside-toplevel
from .config import save_default
if args.verbose:
print(
"Saving {}".format(
os.path.join(
working_directory,
args.rules_file)))
return save_default(working_directory, destinationfile=args.rules_file)
parsed = parser.parse_args(args=args)

# If --generate-rules was created, output the file, and exit
error = do_generate_build_rules(parsed, working_directory)
if error is not None:
return error

# If invoked without any parameters, try if build_rules.py
# has a list of projects to build
if args is None and len(sys.argv) < 2:
error = process_makeprojects(parsed, working_directory)
if error is not None:
return error

# Make a list of directories to process
if not args.directories:
args.directories = (working_directory,)
if not parsed.directories:
parsed.directories = (working_directory,)

# Process the directories
for item in args.directories:
error = process(os.path.abspath(item), args)
for item in parsed.directories:
error = process(os.path.abspath(item), parsed)
if error:
break
else:
if args.verbose:
if parsed.verbose:
print("Makeprojects successful!")
error = 0

Expand Down
12 changes: 12 additions & 0 deletions makeprojects/build_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@
# Can be overridden above
PROCESS_PROJECT_FILES = True

# List of projects to generate if makeprojects is invoked
# without any parameters, default create recommended
# project for the host machine
MAKEPROJECTS = (
# This example builds Visual Studio 2019 and 2022 for Windows
# {"platform": "windows",
# "type": "library",
# "name": "project",
# "configuration": "Release",
# "ide": ("vs2019", "vs2022")},
)

########################################


Expand Down
Loading

0 comments on commit 8393037

Please sign in to comment.